====== 名前付きパイプ(FIFO)経由でログを受信するスクリプト ====== デーモンではないプログラムをnohupなどから起動する方法で常駐させるのは良いとしても、その出力をログに記録するときには少々問題がある。 * nohupを使うのでSIGHUPは無視される。 * 標準出力のリダイレクトでログ出力をしていると、ログのローテーションができない。(TIPS追記) そこでプログラムからの出力は名前付きパイプ(FIFO)に対して行い、別のプロセスからログファイルに書き込むようにする。 ===== ログ受信スクリプト ===== 名前付きパイプ(FIFO)からログを受信しファイルに書き込むスクリプト #!/bin/sh FIFO=/var/tmp/logpipe PID=/run/receive-log LOG=/var/log/pipe.log if [ -n "$1" ] then LOG=$1 fi echo $$ > ${PID} test -p ${FIFO} || mkfifo ${FIFO} trap receive_SIGHUP 1 trap receive_SIGTERM 15 # --- Functions receive_SIGHUP () { daytime=`date '+%Y-%m-%dT%H:%M:%S%z'` echo "Received SIGHUP" 1>&2 sleep 10 } receive_SIGTERM() { daytime=`date '+%Y-%m-%dT%H:%M:%S%z'` echo "Received SIGTERM" 1>&2 rm ${PID} exit 0 } # --- Main while true do if [ -p ${FIFO} ] then read line <${FIFO} test -n "${line}" && echo ${line} >> ${LOG} else sleep 1 fi done 2>/dev/null ==== ログ受信スクリプトのサービス定義 ==== ログ受信スクリプトをsystemdのサービスとして定義するファイル [Unit] Description="pipe log receiver" Before=pipe.service [Service] Type=simple ExecStart="/usr/local/bin/receive-log" KillMode=process PIDFile=/run/receive-log StandardOutput=syslog StandardError=syslog SyslogIdentifier=receive-log [Install] WantedBy=default.target ===== テスト用ログ送信スクリプト ===== ログ出力を確認するためのテスト用ログをパイプに送信するスクリプト #!/bin/sh FIFO=/var/tmp/logpipe while true do date '+%Y-%m-%dT%H:%M:%S%z' > ${FIFO} sleep 5 done ===== TIPS ===== ログファイルを切り替えないプロセスに対し、logrotateでは[[https://hackers-high.com/linux/man-jp-logrotate/#copytruncate|コピーを作成した後に元のログファイルを空にする]]こともできる。\\ ただし、ログ切替時に書き込まれたログは失われる可能性がある。