在 Bash 脚本中使用日志记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8273089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use logging in Bash script
提问by Sibi JV
I have a bash script from which i need to write logs. currently i use block like the one below
我有一个 bash 脚本,我需要从中编写日志。目前我使用像下面这样的块
#log stop request
{
local now=$(date +"%a %b %d %Y %H:%M:%S")
printf "batch stop request successful. \n"
printf " Time :: %s\n" "$now"
printf " PID of process :: %s\n" ${PID[0]}"
} >> "${mylogfile}"
where mylogfile variable will have name of the logfile.
其中 mylogfile 变量将具有日志文件的名称。
The problem with this approach is that when 2 or more instances are running, the logs tends to get messed up with writes from instances coming interleaved.
这种方法的问题在于,当 2 个或更多实例正在运行时,日志往往会与来自交错实例的写入混淆。
Please note i used the block thinking that it would result in the log being written to file in one go, thus avoiding the problem.
请注意,我使用块认为它会导致日志一次性写入文件,从而避免了这个问题。
I have seen logger command from Vivek Gite post. but the problem is it does not write to a file I can specify, rather does so to /var/log/message.
我看过Vivek Gite 帖子中的记录器命令。但问题是它不会写入我可以指定的文件,而是写入 /var/log/message。
Any help is much appreciated.
任何帮助深表感谢。
Thanks and Regards Sibi
感谢和问候 Sibi
回答by Adam Zalcman
POSIX (IEEE Std 1003.1-2001) does not define the behavior of concurrent write()syscalls sending data to the same file, hence you may obtain different results depending on your platform. You can try to merge all printfsinto one in the hope that this will work, but even if it does there is no guarantee that it will in the future or on a different platform.
POSIX (IEEE Std 1003.1-2001) 没有定义并发write()系统调用将数据发送到同一文件的行为,因此您可能会根据您的平台获得不同的结果。您可以尝试将所有内容合并printfs为一个,希望这会奏效,但即使如此,也不能保证将来或在不同的平台上会如此。
Rather than using concurrency control and flushing to ensure the writes are sequenced, you can send the messages to a third process which will write your log messages sequentially to a file on behalf on all the processes. In fact, this is what is done with loggerand syslogin the postyou cited. The loggercommand does not send the messages to /var/log/messages. It sends the log messages to syslogwhich can be configured to save the log messages anywhere you like. Changing this configuration usually requires administrative privileges, though.
您可以将消息发送到第三个进程,该进程将代表所有进程将日志消息按顺序写入文件,而不是使用并发控制和刷新来确保写入是有序的。事实上,这是与完成logger,并syslog在后您引用。该logger命令不会将消息发送到/var/log/messages。它发送日志消息syslog,可以配置为将日志消息保存在您喜欢的任何位置。但是,更改此配置通常需要管理权限。
If you can't or don't want to use syslog, you can also use netcatas a logging server. Run this to multiplex all incoming log messages from all scripts into the file (this job should remain running in the background all the time, you can also run it in a screen):
如果您不能或不想使用syslog,您还可以使用netcat作为日志服务器。运行它以将来自所有脚本的所有传入日志消息多路复用到文件中(此作业应始终在后台运行,您也可以在屏幕中运行它):
nc -luk localhost 9876 > shared_log_file &
(port 9876 is just an example) and log in each script this way:
(端口 9876 只是一个示例)并以这种方式登录每个脚本:
printf "Log message\n" > /dev/udp/localhost/9876
You can also use a custom UDP server instead of netcat (e.g. like this one).
您还可以使用自定义 UDP 服务器而不是 netcat(例如,像这样)。
回答by jkh
The block does not group the printfs in any way, as you have discovered. What you could do, however, is do all of those commands in a sub-shell (between parenthesis) and then redirect the sub-shell's output!
正如您所发现的,该块不会以任何方式对 printf 进行分组。但是,您可以做的是在子外壳程序中(在括号之间)执行所有这些命令,然后重定向子外壳程序的输出!
回答by thiton
Depending on the nature of your logging, it might be well-suited for the system log instead of its private logfile. In this case, the loggerprogram could be a very good alternative to hand-rolled logging.
根据日志的性质,它可能更适合系统日志而不是其私有日志文件。在这种情况下,该logger程序可能是手动日志记录的一个很好的替代方案。
回答by shellter
Trying putting the 3 printfs as one string, i.e.
尝试将 3 个 printfs 作为一个字符串,即
printf "Epsilon batch stop request successful. \n Time :: %s\n PID of process :: %s\n" "$now" ${PID[0]}
You may still get interleaving.
你可能仍然会交错。
Why not start each instance with its own log file, using the ${PID} on your logfile name to keep them separate? i.e.
为什么不使用自己的日志文件启动每个实例,使用日志文件名中的 ${PID} 将它们分开?IE
>> "${mylogfile}.${PID}"
Edit
编辑
As you're hoping for logger, check out the man page :
当您希望使用 logger 时,请查看手册页:
logger(1) - Linux man page
Name
logger - a shell command interface to the syslog(3) system log module
Synopsis
logger [-isd] [-f file] [-p pri] [-t tag] [-u socket] [message ...]
Description
Logger makes entries in the system log. It provides a shell command interface to the syslog(3) system log module.
Options:
-i' Log the process id of the logger process with each line.
-s' Log the message to standard error, as well as the system log.
-f file
Log the specified file.
.....
That looks like what you want.
这看起来像你想要的。
I hope this helps.
我希望这有帮助。

