Mencatat Output Daemon dengan Pemula

34

Saya memiliki daemon khusus yang dikelola oleh pemula di server Ubuntu saya. Ini berfungsi dengan baik kecuali bahwa saya perlu menangkap (log) output daemon. The halaman bait resmi mengatakan bahwa saya dapat menggunakan console loggeduntuk melakukan hal ini, tetapi file apa itu log ke?

Saya juga sudah membaca bahwa baitconsole logged itu tidak lagi sahih . Saya saat ini menggunakan 0.3.9 (Hardy) tetapi akan meningkatkan ke 0.6.x (Lucid) dalam beberapa bulan. Jika console loggedsebenarnya tidak akan berfungsi dengan versi yang lebih baru, apa yang harus saya gunakan?

Alex Reisner
sumber
1
Bisakah Anda memperbarui daemon khusus Anda untuk mengirim output ke syslog, atau ke file log yang ditentukan dalam file konfigurasi daemon?
Zoredache

Jawaban:

35

Cuplikan ini akan menyalurkan output layanan Anda ke logger, sambil tetap memungkinkan Anda untuk menjalankan proses layanan (sehingga mengganti proses shell) sehingga pemula tidak menjadi bingung. Itu juga memastikan proses logger direparasi ke init, jadi itu bukan anak dari layanan Anda, dan itu menghindari meninggalkan cruft duduk-duduk di sistem file, meskipun itu perlu membuat fifo sementara.

script
  mkfifo /tmp/myservice-log-fifo
  ( logger -t myservice </tmp/myservice-log-fifo & )
  exec >/tmp/myservice-log-fifo
  rm /tmp/myservice-log-fifo
  exec myservice 2>/dev/null
end script

Begini cara kerjanya:

  1. mkfifo /tmp/myservice-log-fifocukup buat file khusus fifo (alias pipa bernama). Ketik man 7 fifountuk info lebih lanjut.
  2. ( logger ... </tmp/myservice-log-fifo & ) mulai membaca logger dari fifo, di latar belakang. Parens menyebabkan proses logger untuk reparents untuk init, daripada tetap anak proses shell saat ini.
  3. exec >/tmp/myservice-log-fifomengalihkan stdout shell saat ini ke fifo. Sekarang kita memiliki deskriptor file terbuka untuk fifo itu, dan kita sebenarnya tidak memerlukan entri sistem file lagi ...
  4. rm /tmp/myservice-log-fifo jadi kami akan menghapusnya.
  5. exec myservice 2>/dev/nullcukup menjalankan layanan dengan cara biasa. Stdout sudah menuju ke fifo, dan itu tidak akan berubah ketika program baru dijalankan.

UPDATE: set -e tidak diperlukan karena Upstart menjalankan skrip dengan opsi ini secara default (lihat http://upstart.ubuntu.com/cookbook/#develop-scripts-using-bin-sh )

Keith Rarick
sumber
jawaban yang bagus, dan tidak meninggalkan file fifo di mana pun.
Ash Berlin-Taylor
Apa itu set -e?
Peter Mounce
1
The set -emenyebabkan script untuk keluar segera jika perintah apapun gagal. Tanpa baris itu, skrip akan terus menjalankan perintah berikutnya dengan sia-sia (dan mungkin berbahaya).
Keith Rarick
1
Untuk mencatat stderr dan stdout, tambahkan baris di exec 2>&1atas rmbaris, dan hapus 2>/dev/nulldari baris terakhir.
itsadok
31

Untuk versi Ubuntu terbaru (12.04+), cukup gunakan

console log

Dan output daemon (STDOUT & STDERR) akan ditambahkan ke /var/log/upstart/<service>.log

http://upstart.ubuntu.com/cookbook/#console-log

Willem
sumber
2
Itu akan bersih dan menyenangkan, tetapi sayangnya itu tidak bekerja pada CentOS 6.x yang masih mengirimkan versi kuno pemula yang tidak mendukung ini.
Cristian Măgherușan-Stanciu
11

Jika Anda menggunakan console output bait , dan kemudian menyalurkan output skrip Anda ke logger(antarmuka perintah shell ke modul log sistem syslog (3)) maka itu akan berhasil.

Sebagai contoh

console output
exec /my/script | logger

akan masuk /var/log/messages

Sebagai contoh

console output
exec /my/script | logger -t my-script

akan masuk /var/log/messagesdan menandai setiap pesan denganmy-script

logger --help untuk opsi penggunaan logger.

(Saya menggunakan Amazon Linux AMI, yang berbasis Centos 5.x; YMMV)

Peter Mounce
sumber
4
Ternyata ini bukan solusi yang baik. pemula kait ke PID logger, bukan dari proses yang sebenarnya Anda inginkan untuk mengelola.
Peter Mounce
10

Saya tidak mendapatkan mkfifotrik untuk bekerja dengan memuaskan; tampaknya tidak menangkap stderr, dan upaya untuk mengarahkan menyebabkan Upstart gagal tanpa kesalahan.

Ini juga memiliki efek samping yang disayangkan membuat loggerproses berkeliaran sebagai seorang anak init, sehingga informasi tentang siapa "yang memiliki" penebang hilang, dan siapa pun yang belum sadar mkfifoakan menganggap itu adalah proses menjuntai yang dapat dibunuh.

Alih-alih saya berakhir dengan solusi berikut, yang menyelesaikan semua masalah ini. Itu menyebabkan logger menjadi proses anak, sambil menjaga layanan sebagai proses root. Sayangnya, ini membutuhkan eksekusi bash, tetapi itu hanya terlihat kotor.

script
  # ... setup commands here, e.g. environment, cd, ...
  exec bash <<EOT
    exec 1> >(logger -t myservice) 2>&1
    exec myservice
EOT
end script

Ini menggunakan trik yang mengarahkan ulang stdout dan stderr ke sebuah perintah. Karena kami mengeksekusi layanan di dalam bashperintah, ini memiliki efek samping mengganti shell dan secara ajaib menjadikan bash menjadi proses turunan dari layanan, seperti yang ditunjukkan oleh ps aufxw:

myservice 
 \_ bash -c exec 1> >(logger -t myservice) 2>&1 && exec myservice
    \_ logger -t myservice

Untuk beberapa alasan perintah di atas harus dibungkus dengan a bash -c. Saya berasumsi ini karena Pemula hanya berpura-pura menjalankan skrip Anda melalui Bash, tetapi sebenarnya tidak. Jika ada yang bisa menyarankan cara untuk menghindari shell bash ekstra, itu akan luar biasa.

Alexander Staubo
sumber
1
Iya nih! Saya sangat senang menemukan ini. Terlihat lebih baik daripada varian mkfifo dan dalam kasus saya, saya perlu exec bash -l << EOFjadi tidak ada kerugian di sana.
thom_nic
6

Ini jelek tapi sejauh ini yang terbaik yang saya temukan

exec / path / ke / server >> /tmp/upstart.log 2> & 1

Jorge Vargas
sumber
2
Solusinya tidak baik ketika datang ke rotasi log, karena aplikasi ini masuk langsung ke file. Masuk melalui syslog menghindari masalah terkait.
Mark Stosberg
3

Anda juga dapat mengarahkan output ke syslog, mis

exec $SERVER 2>&1 | logger -t myservice -p local0.info

Namun, pipeline dapat menyebabkan pemula untuk membingungkan PID dari proses logging dengan PID daemon.

Nikratio
sumber
Daemon yang membingungkan PID sebenarnya adalah daemon yang tidak berguna, karena ia seharusnya menyaksikan prosesnya, kemudian respawn. Adakah ide untuk memastikan PID yang tepat sedang diawasi?
Johann Philipp Strathausen
Saya pikir (tetapi belum mencoba) bahwa Anda akan menginginkan expect forkatau expect daemonbait. Atau Anda bisa catmem-file pid ke dalam pesan log sebaliknya, saya kira.
Peter Mounce
1

Alternatif lain menggunakan tee seperti:

exec $SERVER 2>&1 | tee /dev/stderr | logger -t myservice

untuk mendapatkan file baru, dan output syslog

perl
sumber