Bagaimana saya bisa log stdout dari proses yang dimulai oleh start-stop-daemon?

120

Saya menggunakan skrip init untuk menjalankan proses sederhana, yang dimulai dengan:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS

Proses yang disebut $ DAEMON biasanya mencetak informasi log ke keluaran standarnya. Sejauh yang saya tahu, data ini tidak disimpan di mana pun.

Saya ingin menulis atau menambahkan stdout $ DAEMON ke file di suatu tempat.

Satu-satunya solusi yang saya tahu adalah memberi tahu start-stop-daemon untuk memanggil shellscript alih-alih $ DAEMON secara langsung; skrip kemudian memanggil $ DAEMON dan menulis ke logfile. Tapi itu membutuhkan skrip tambahan yang, seperti memodifikasi daemon itu sendiri, tampaknya cara yang salah untuk menyelesaikan tugas umum semacam itu.

joeytwiddle
sumber

Jawaban:

127

Untuk memperluas jawaban ypocat, karena itu tidak mengizinkan saya berkomentar:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
 --make-pidfile --pidfile $PIDFILE --background       \
 --startas /bin/bash -- -c "exec $DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Menggunakan execuntuk menjalankan daemon memungkinkan stop untuk menghentikan proses turunan dengan benar, bukan hanya bash induk.

Menggunakan --startasalih-alih --execmemastikan bahwa proses akan dideteksi dengan benar oleh pid-nya dan tidak akan secara keliru memulai banyak contoh daemon jika start dipanggil beberapa kali. Jika tidak, start-stop-daemon akan mencari proses / bin / bash dan mengabaikan proses anak sebenarnya yang menjalankan daemon.

stormbeta
sumber
2
Ini adalah solusi yang jauh lebih baik daripada solusi @ypocat terutama karena mematikan daemon lagi dengan menggantinya --startdengan --stopbenar - benar berfungsi.
aef
Saya mencoba menjalankan perintah ini dari rc.local daripada init.d ... Sepertinya saya tidak mendapatkan hasil yang sama. Namun saat menjalankannya dari shell melalui SSH, ini bekerja seperti pesona!
nemo
1
start-stop-daemon --test (...)Seperti apa tampilan yang menyertainya ?
Abdull
2
@MattClimbs Ini menimpa file setelah setiap awal. gunakan, >>bukan >untuk menambahkan.
Meong
2
Sebelum Anda panik (seperti saya) karena log Anda kosong, waspadalah bahwa ini buffer! Anda dapat menggunakan "exec stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2> & 1" untuk memaksa keluaran mengosongkan setiap baris (dari blog.lanyonm.org/articles/2015/01/11/… )
piers7
47

Anda perlu melakukan:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec /bin/bash -- -c "$DAEMON $DAEMON_ARGS > /var/log/some.log 2>&1"

Juga jika Anda menggunakan --chuidatau --user, pastikan pengguna dapat menulis ke /var/logatau yang sudah ada /var/log/some.log. Cara terbaik adalah dengan meminta pengguna tersebut memiliki /var/log/subdir/.

youurayy
sumber
1
Fantastis, terima kasih ypocat. Hari ini, selain menyimpan log, saya perlu menjalankan skrip non-biner yang --exec tidak mengizinkannya tetapi trik Anda berhasil!
joeytwiddle
8
Sisi negatifnya ... menghentikan layanan akan membunuh bash, tetapi bukan proses anak bash dimulai! (Dalam kasus saya, DAEMON = kopi).
joeytwiddle
1
Saya mengatasinya dengan menghentikan semua proses anak dari proses bash di bagian atas do_stop. bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
joeytwiddle
5
Baik untuk diketahui, dan pkillsolusinya juga. Ingin tahu apa yang akan dilakukan ... -c "exec $DAEMON..."(menambahkan "exec"). Tidak ada ini di piring sekarang jadi tidak bisa mencobanya.
youurayy
12
@ypocat Saya baru saja memverifikasi bahwa ini berfungsi dengan -c "exec $ DAEMON ...". Ini berarti tidak diperlukan peretasan pkill.
terlalu memikirkan
40

Tampaknya Anda sekarang dapat menggunakan --no-closeparameter tersebut saat mulai start-stop-daemonmenangkap keluaran daemon. Fitur baru ini tersedia dalam dpkgpaket sejak versi 1.16.5 di Debian:

Tambahkan opsi --no-close baru untuk menonaktifkan fds penutup di --background.

Ini memungkinkan pemanggil untuk melihat pesan proses untuk tujuan debugging, atau untuk dapat mengarahkan deskriptor file ke file log, syslog atau yang serupa.

Stéphane
sumber
8
Sayang sekali itu tidak tersedia di Ubuntu 12.04 :(
Leon Radley
Sepertinya saya tidak bisa mendapatkannya --tidak-hampir bekerja ... hasilnya masih menuju ke shell yang saya
jalankan
+1 Bekerja dengan sempurna pada pemerasan Debian dengan layanan node.js daemonized.
speakr
2
@stantonk Apakah Anda juga menyalurkan stdout / stderr ke file? Baris perintah lengkap terlihat seperti berikut. Dan pastikan bahwa logfile dapat ditulis oleh pengguna $ USER: start-stop-daemon --start --chuid $ USER --pidfile $ PIDFILE --background --no-close --make-pidfile --exec $ DAEMON - $ DAEMONARGS >> /var/log/xxxxx.log 2> & 1
nharrer
1
Ini tidak tersedia dengan openrc start-stop-daemon. Namun versi openrc memiliki opsi -1dan -2untuk mengarahkan stdout dan stderr masing-masing.
little-dude
14

Dengan openrc (yang merupakan default pada gentoo atau alpine linux misalnya) start-stop-daemonmemiliki opsi -1dan -2:

-1, --stdout Alihkan stdout ke file

-2, --stderr Alihkan stderr ke file

Jadi Anda bisa menulis:

start-stop-daemon --start --quiet --chuid $DAEMONUSER    \
    --make-pidfile --pidfile $PIDFILE --background       \
    --exec $DAEMON $DAEMON_ARGS -1 $LOGFILE -2 $LOGFILE
anak kecil
sumber
9

Tidak terlalu sulit untuk menangkap keluaran daemon dan menyimpannya ke file:

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas $DAEMON --no-close \
  -- $DAEMON_ARGS >> $LOGFILE 2>&1

Namun solusi ini mungkin kurang optimal logrotate.

Mungkin lebih baik untuk menangkap keluaran ke syslog. Di Debian, ini akan cocok dengan perilaku layanan systemd. Upaya langsung berikut untuk menulis ulang contoh di atas salah karena meninggalkan dua proses tanpa induk ("zombie") (pencatat dan daemon) setelah menghentikan daemon karena start-stop-daemonhanya menghentikan anaknya tetapi tidak semua turunannya:

## Do not use this!
start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /bin/sh \
  -- -c """exec $DAEMON $DAEMON_ARGS | /usr/bin/logger --tag $NAME"""

Untuk membuatnya bekerja kita membutuhkan pembungkus yang menghentikan anak-anaknya setelah menerima SIGTERMdari start-stop-daemon. Ada beberapa:

duende :
start-stop-daemon --start --background \
  --pidfile $PIDFILE \
  --startas /usr/sbin/duende \
  -- --pid $PIDFILE --chroot=/ --uid 65534 --ident $NAME \
  /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec ${DAEMON} $DAEMON_ARGS"""

Catatan: uid=65534adalah pengguna nobody.

Kelebihan : ini bekerja dan relatif mudah.
Kekurangan : 4 proses (supervisor duende, forknya dengan hak istimewa yang dijatuhkan (logger), sudan daemon itu sendiri); wajib --chroot; Jika daemon langsung berhenti (mis. Perintah tidak valid) status_of_proc -p $PIDFILE "$DAEMON" "$NAME"laporkan sebagai berhasil dimulai.

daemon :
start-stop-daemon --start --pidfile $PIDFILE \
  --startas /usr/bin/daemon \
  -- --noconfig --name $NAME --stderr=syslog.info --stdout=syslog.info \
  -- /bin/su --login $DAEMON_USER --shell /bin/sh --command """exec $DAEMON $DAEMON_ARGS"""

Kelebihan : 3 proses (supervisor daemon, sudan daemon itu sendiri).
Kekurangan : Sulit untuk dikelola $PIDFILEkarena opsi baris perintah daemon yang membingungkan ; Jika daemon langsung berhenti (mis. Perintah tidak valid) status_of_proc -p $PIDFILE "$DAEMON" "$NAME"laporkan sebagai berhasil dimulai.

pipexec ( pemenang ):

start-stop-daemon --start --background \
  --pidfile $PIDFILE --make-pidfile \
  --chuid $DAEMON_USER \
  --startas /usr/bin/pipexec -- -k \
   -- [ D $DAEMON $DAEMON_ARGS ] [ L /usr/bin/logger --tag $NAME ] '{D:2>D:1}' '{D:1>L:0}'

Kelebihan : 3 proses (supervisor pipexec, loggerdan daemon itu sendiri); Jika daemon langsung berhenti (mis. Perintah tidak valid) status_of_proc -p $PIDFILE "$DAEMON" "$NAME"laporkan kegagalan dengan benar.
Kekurangan : tidak ada.

Inilah pemenangnya - solusi termudah dan rapi yang tampaknya berfungsi dengan baik.

Hanya pekerjaan
sumber
7

Biasanya start-stop-daemon menutup deskriptor file standar saat berjalan di latar belakang. Dari halaman manual start-stop-daemon:

-C, --tidak-tutup
Jangan menutup deskriptor file apa pun saat memaksa daemon ke latar belakang. Digunakan untuk tujuan debugging untuk melihat keluaran proses, atau untuk mengarahkan deskriptor file ke log keluaran proses. Hanya relevan saat menggunakan --background.

Yang ini berhasil untuk saya:

    start-stop-daemon -b -C -o -c \ 
         $DAEMON_USER -S -x $DAEMON > $DAEMON_LOG 2>&1
Raashid Muhammad
sumber
4

Mengutip milis lama:

https://lists.ubuntu.com/archives/ubuntu-uk/2005-June/000037.html

Cara yang mudah - dan jika Anda ingin menggunakan start-stop-daemon mungkin satu-satunya - cara untuk mengatasinya adalah dengan membuat skrip kecil yang berisi:

#!/bin/sh
exec /home/boinc/boinc/boinc > /home/boinc/log/boinc.log

dan kemudian gunakan skrip itu sebagai argumen untuk start-stop-daemon.

Mungkin pertanyaan sebenarnya adalah apakah benar-benar perlu menggunakan start-stop-daemon di tempat pertama?

joeytwiddle
sumber
3

Saya tidak yakin apakah "$ DAEMON $ DAEMON_ARGS> /var/log/some.log 2> & 1" akan menutup deskriptor file untuk file log ... yang berarti jika daemon Anda berjalan selamanya, saya tidak yakin bahwa logrotate atau mekanisme lain untuk membersihkan ruang disk akan berfungsi. Karena ini> bukannya >>, perintah yang disarankan juga akan memotong log yang ada saat restart. Jika Anda ingin melihat mengapa daemon macet, dan restart otomatis, itu mungkin tidak terlalu membantu.

Pilihan lain mungkin adalah "$ DAEMON | logger". logger adalah perintah yang akan masuk ke syslog (/ var / log / messages). Jika Anda membutuhkan stderr juga, saya rasa Anda dapat menggunakan "$ DAEMON 1> & 2 | logger"

nairbv.dll
sumber
Anda benar, penggunaan >>umumnya lebih sesuai untuk daemon, meskipun ini berarti Anda sekarang harus membuat aturan logrotate!
joeytwiddle
Sedangkan untuk ruang disk, metode yang memotong file akan segera mendapatkan kembali ruang tersebut (setidaknya di bawah sistem file ext). Namun berhati-hatilah dengan metode yang hanya menghapus file yang masih ditulis: ruang tidak akan diambil kembali sampai pegangan dilepaskan, dan Anda tidak dapat lagi menemukan node file untuk memotongnya secara manual!
joeytwiddle
@joeytwiddle bagian dari maksud saya di sini adalah bahwa ada situasi di mana logrotate akan gagal untuk memutar log jika pegangan file tidak pernah ditutup.
nairbv
--no-close ... | loggertidak berfungsi untuk saya (Debian 7.3, start-stop-daemon 1.16.12). Skrip start-stop-daemon tidak kembali, meskipun / var / log / messages diisi :-). Saya mencobanya dengan dan tanpa 1>&2.
hgoebl
hgoebl Anda harus memiliki ekspresi "cmd | logger" dalam tanda kutip, sehingga penerjemah akan tahu itu "cmd" yang Anda gunakan untuk logger, bukan ekspresi start-stop-daemon.
Wexxor
2

Dengan asumsi itu bash (meskipun beberapa shell lain mungkin mengizinkan ini juga), baris:

exec >>/tmp/myDaemon.log

akan mengirim semua keluaran standar masa depan ke file itu. Itu karena exectanpa nama program hanya melakukan sihir pengalihan. Dari bashhalaman manual:

Jika perintah tidak ditentukan, setiap pengalihan akan diterapkan di shell saat ini.

Manajemen file tersebut tentu saja merupakan masalah lain.

paxdiablo
sumber
dapatkah Anda menjelaskan di mana garis ini seharusnya ditempatkan? Tepat setelah start-stop-daemonbaris pertanyaan awal yang disebutkan?
Abdull
1

Bagaimana tentang:

sudo -u myuser -i start-stop-daemon ...
jakub.piasecki
sumber