我有一个简短的脚本,该脚本由系统守护程序针对特定事件执行。我知道事件正在发生并且脚本正在执行,但是它没有达到我的预期。奇怪的是,当我手动运行它时确实如此,所以我很困惑。
我怎么知道发生了什么事?该脚本基本上是一系列命令,如下所示:
/bin/foo on 3
sudo bar a
我有一个简短的脚本,该脚本由系统守护程序针对特定事件执行。我知道事件正在发生并且脚本正在执行,但是它没有达到我的预期。奇怪的是,当我手动运行它时确实如此,所以我很困惑。
我怎么知道发生了什么事?该脚本基本上是一系列命令,如下所示:
/bin/foo on 3
sudo bar a
Answers:
首先,如果脚本由系统守护程序运行,并且该守护程序以root特权运行,则无需使用sudo
。这包括init
(和systemd
),其中包括rc.local
。如果该守护程序未以root特权运行,则sudo
除非/etc/sudoers
配置为允许该守护程序(并且没有密码),否则它将无法工作。Raspbian用户可能对此感到困惑,因为pi
默认情况下允许该用户执行任何操作(如果您查看,/etc/sudoers
则会看到如何完成此操作)。
接下来,您可以bash
通过在子shell中执行以下命令来捕获来自任何脚本或bash脚本内的任何命令集的输出:1
(
/bin/foo on 3
sudo bar a
) &> /var/log/myTestLog.txt
该()
指示子shell。此内部任何内容的所有输出都将重定向到/var/log/myTestLog.txt
文件。一些注意事项:
&>
是一种bashism,因此,如果脚本是通过第一行的shebang执行的,那么它应该是#!/bin/bash
,而不仅仅是/bin/sh
。“ Bashisms”仅在bash
外壳中起作用。
这包括/etc/rc.local
,默认情况下会使用,/bin/sh
(是的,您可以放心地将其更改为/bin/bash
)。
/var/log
需要root特权才能写入。如果该过程没有,请使用或创建一个您知道可以的目录。如有疑问,如果无需关闭或重新启动系统即可进行测试,请使用/tmp
,该功能可在世界范围内写入(即任何人均可)。但是/tmp
不会在整个靴子上持续存在。它也是基于RAM的小型分区,因此请勿向其写入大量数据。它不是您的SD卡(实际上是在Raspbian的当前版本中,但实际上不要指望它)。
&>
将覆盖中的任何内容myTestLog.txt
。相反,如果您想追加到现有日志(出于调试目的而可能是个好主意),请使用&>>
。然后,您可以将命令添加到该子shell的开头,如下所示:
echo Starting $(date)
从每次运行中分离信息。如果不确定这样做是什么,请在命令行上尝试。
最后一点很好地说明了您可以对不输出任何命令的命令可以执行的操作,但是如果包含(例如)-v
“冗长” 命令,则大多数命令都可以执行。注意某些命令-v
意味着“打印版本信息”。在手册页中查看该命令,以确保该命令是否起作用以及如何起作用(某些命令使用的开关也不同于-v
)。
按照约定,命令完成后还返回0值。有时将其称为“退出状态”,您通常看不到它,但是shell会显示echo $?
。尝试
ls /
echo $?
ls /nonexistantdir
echo $?
您将得到0和2。如果然后在手册页中的ls
“退出状态”下查找,则会看到非常不确定的,含糊的:
2 if serious trouble (e.g., cannot access command-line argument).
可能总比没有好,但总有可能。
至少,这表明命令由于某种原因而失败。退出状态还允许您执行以下操作:
/bin/foo && sudo bar
在&&
这种情况下的意思是“如果第一个命令成功”,假设第一个命令使用返回0的约定(这就是为什么他们通常做的)。如果/bin/foo
不起作用,找不到等等,那么sudo bar
就永远不会发生。
结合使用日志记录消息和条件执行(&&
)应该可以使您更接近于解决问题,或者至少获得对其他人可能有用的信息,以帮助您解决问题。 没有这个,其他人最常做的就是猜测。
1.您可以使用以下命令从内部完成整个脚本的相同输出重定向:
exec &> /var/log/myTestLog.txt
在顶部(或任何位置,它将应用于随后的所有内容)。
人们通常会忘记将脚本作为守护程序运行时的一个重要方面是shell环境,$PATH
尤其是变量。在您的示例中,第二行依赖于$PATH
:sudo
is 的全名/usr/bin/sudo
,并且您的用户外壳程序仅知道这一点,因为/usr/bin
在寻找可执行文件时会告诉用户进行搜索。的情况也是如此bar
。
考虑到将sudo
脚本作为守护程序运行时不需要这样做,第二行应如下所示:
/path/to/bar a
U&L
。我误读了标题,建议“记录用于调试的系统脚本的输出”将使目的更清楚。另外,当我阅读这些foo
bar
示例时,我的大脑也停滞不前,我更喜欢看起来更真实的东西。我不愿意编辑任何帖子,因此,如果您认为可以改进,请留给您。