我有一个 shell 脚本,它将输出写入 some_log_file.log 文件。
{
some logic..
if grep -iq "No such file or directory" some_log_file.log ; then
some logic to send email.. attaching the same some_log_file.log
fi
} >> some_log_file.log 2>&1
如果您观察上面的代码,就会发现脚本在运行时正在检查它正在写入的同一日志文件。这是有效的。但是,这是允许的、标准的吗?
答案1
是的,这是允许的。不,我认为这不是很常见或标准。不过,既然它正在工作,你就可以保持原样。
但就 Panki 的观点而言:仅检查可能报告“没有此类文件或目录”的命令的退出状态(又称返回状态)而不是 grep 日志会更好、更高效。
变量$?始终包含最后执行的命令的退出状态。通常为 0 表示命令运行成功。如果它是正值(1、2、99,等等),则表明存在某种类型的故障。例如:
>> ls /usr/bin/sed
-rwxr-xr-x 1 root wheel 202960 May 9 15:30 /usr/bin/sed
>> echo $?
0
>> ls -l nonexistent_file
ls: nonexistent_file: No such file or directory
>> echo $?
1
您的命令可能会报告“没有这样的文件或目录”,ftp 是什么?为了简单起见,我们假设它是“ls”。您的脚本可能如下所示:
ls $my_file # Or whatever your command is.
if [ $? = 1 ]; then
# Send mail ...
fi
# Alternatives:
ls $my_file # Or whatever your command is.
if [ $? != 0 ]; then
# Send mail ...
fi
ls $my_file # Or whatever your command is.
status=$?
case $status in
0) : ;; # Success, do nothing.
1) Send mail ... ;;
*) echo "Error: \"ls $my_file\"." returned status $status."
exit 99;;
esac
如果您的命令是 ftp,则该命令具有更复杂的状态代码,解释如下:
https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
和这里:
https://docs.microsoft.com/en-us/troubleshoot/developer/webapps/iis/ftp-service-svchost-inetinfo/ftp-status-codes-iis-7-and-later-versions
您还可以使用带有 -f(跟随)选项的 tail 命令进行调查。例如,您可以在后台运行如下命令:
tail -f some_log_file.log | grep -iq "No such file or directory"
有关详细信息,请参阅 tail man(手册)页面。
但我认为使用退出状态($?)将是您的最佳选择。
答案2
对它附加到的文件执行阻塞读取的脚本通常会以挂起的进程结束。
通常的读写工作流程是这样的:脚本等待下一行出现,对其进行处理,并写入一些输出,然后返回等待下一行。
当输出转到脚本正在读取的同一文件时,最终脚本的读取会赶上它正在写入的文件中的同一点。此时,脚本会等待下一行,但在脚本写入一些行之前,不会出现行,并且在脚本读取一些新行之前,不会出现这种情况。剧本挂了。
如果其他进程也在写入该文件,则不会发生这种情况。但这通常是一种需要避免的情况。