====== 名前付きパイプ(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|コピーを作成した後に元のログファイルを空にする]]こともできる。\\
ただし、ログ切替時に書き込まれたログは失われる可能性がある。