デーモンではないプログラムをnohupなどから起動する方法で常駐させるのは良いとしても、その出力をログに記録するときには少々問題がある。
そこでプログラムからの出力は名前付きパイプ(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
ログファイルを切り替えないプロセスに対し、logrotateではコピーを作成した後に元のログファイルを空にすることもできる。
ただし、ログ切替時に書き込まれたログは失われる可能性がある。