TL;DR
Stack Exchangeにそのものドンピシャな回答がある。
https://serverfault.com/a/666970
description "prometheus blackbox exporter"
start on runlevel [2345]
stop on runlevel [016]
script
exec bash << EOT
cd /usr/local/opt/blackbox_exporter
exec > >(logger -t blackbox_exporter) 2>&1
exec ./blackbox_exporter
EOT
end script
Why
- CentOS 6で最近系(forkとかしないでフロントエンドで上がり続けてログはstdoutに出す系)のやつを手軽にdaemon化したい
- init scriptを書くのは正直辛い、し、ネットでも良さそうな感じのやつがもう全然見つからなくなってきている
- systemdに慣れすぎて今更bashでプロセス管理をほぼ完全自前で書くのがしんどい
- そもそも最近系はフロントエンドで上がり続ける系が多い
- コンテナとかsystemdではむしろそれが普通なので普通な流れ
- CentOS 6にはupstart入ってるじゃん! → バージョンが古すぎてstdoutをlog出来ない → Stack Exchangeで神回答を発見
Tips
実行ユーザーを変えたい場合は exec bash << EOT
の部分を su hoge << EOT
に変えるだけで対応出来る。
: (snip)
script
exec su nobody << EOT
cd /usr/local/opt/snmp_exporter
exec > >(logger -t snmp_exporter) 2>&1
exec ./snmp_exporter
EOT
end script
rsyslogでファイルを分割したい場合 logger -t
で指定した値を $programname
でマッチしてあげればよい。もしくは logger -p
でfacility.severityを指定出来るので、それを使うでもよい。
if $programname == 'blackbox_exporter' then /var/log/blackbox_exporter.log
& ~
感想とか
このStack Exchangeの回答を見たときに初めてbashの >()
を知った。深い。検索するときは正式名 Process Substitution を覚えてくと良い。これをさらにexecとリダイレクションと組み合わせることで、カレントシェルの標準出力(とSTDERR)先を任意のコマンドに入れ替えてしまうことが出来るんだなあ。逆の <()
はよく使っていて、例えば diff -u <(httpd.conf | sed -e 's/hoge/fuga/g') <(ssh fuga cat /etc/httpd.conf)
とかは頻繁にやる。
単に >()
はカッコ内のコマンドに対して書き込み用のfdを作る。例えば次のようにすると、opensslで鍵ペアを作成するときにファイルに保存せず標準出力に出すことが出来るのか。なるほど!
bash-3.2$ openssl req -new -newkey 2048 -nodes -keyout >(cat) -x509 -subj "/CN=Example Certificate" -days 825 -out >(cat)
Generating a 2048 bit RSA private key
..........................+++
..............................................................+++
writing new private key to '/dev/fd/63'
-----
-----BEGIN PRIVATE KEY-----
: (snip)
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
: (snip)
-----END CERTIFICATE-----