Bagaimana cara mengarahkan output layanan systemd ke file

171

Saya mencoba mengarahkan keluaran systemdlayanan ke file tetapi sepertinya tidak berhasil:

[Unit]
Description=customprocess
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server
StandardOutput=/var/log1.log
StandardError=/var/log2.log
Restart=always

[Install]
WantedBy=multi-user.target

Harap perbaiki pendekatan saya.

saya semua jam
sumber

Jawaban:

233

Saya pikir ada cara yang lebih elegan untuk menyelesaikan masalah: mengirim stdout / stderr ke syslog dengan pengenal dan memerintahkan manajer syslog Anda untuk membagi hasilnya dengan nama program.

Gunakan properti berikut di file unit layanan systemd Anda:

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=<your program identifier> # without any quote

Kemudian, dengan anggapan distribusi Anda menggunakan rsyslog untuk mengelola syslog, buat file /etc/rsyslog.d/<new_file>.confdengan konten berikut:

if $programname == '<your program identifier>' then /path/to/log/file.log
& stop

Sekarang buat file log dapat ditulis oleh syslog:

# ls -alth /var/log/syslog 
-rw-r----- 1 syslog adm 439K Mar  5 19:35 /var/log/syslog
# chown syslog:adm /path/to/log/file.log

Mulai ulang rsyslog ( sudo systemctl restart rsyslog) dan selamat menikmati! Program Anda stdout / stderr masih akan tersedia melalui journalctl ( sudo journalctl -u <your program identifier>) tetapi mereka juga akan tersedia di file pilihan Anda.

Sumber melalui archive.org

Valerio Versace
sumber
8
Tidak bekerja untuk saya di Ubuntu 16.04. journalctl -umasih berfungsi tetapi tidak ada yang dikirim ke file yang ditentukan.
Duncan Calvert
1
Ini berfungsi baik pada bentangan Debian, namun ia mengeluh karena ~sudah usang dan stopharus digunakan sebagai gantinya. Perhatikan juga bahwa baris kedua dapat disingkat menjadi & stopjika keduanya datang setelah satu sama lain.
jlh
47
Dengan systemd 236 atau yang lebih baru Anda juga dapat menulis langsung ke file menggunakan StandardOutput = file: / some / path github.com/systemd/systemd/pull/7198
leezu
5
Saya mendapatkan pekerjaan ini dengan mengubah /etc/rsyslog.d/<newfile>.confisinya menjadi: :programname, isequal, "<your program identifier>" /var/log/somelog.log Berikut ini dokumentasi pada filter rsyslog: rsyslog.com/doc/v8-stable/configuration/filters.html Dan inilah dokumen pada properti seperti programname: rsyslog.com/doc/master/configuration/properties .html
mbil
1
Saya mempunyai masalah menggunakan konfigurasi ini sampai saya menemukan yang rsyslogmemiliki pengguna sendiri syslogdan harus memiliki akses tulis ke lokasi log. Jadi gunakan yang chownsesuai. Semoga ini bisa membantu seseorang.
Imaskar
73

Jika Anda memiliki distro yang lebih baru dengan yang lebih baru systemd( systemdversi 236 atau yang lebih baru ), Anda dapat mengatur nilai StandardOutputatau StandardErrorke file:YOUR_ABSPATH_FILENAME.


Cerita panjang:

Dalam versi yang lebih baru systemdada opsi yang relatif baru ( permintaan github berasal dari 2016 ish dan peningkatannya digabung / ditutup 2017 ish ) di mana Anda dapat mengatur nilai StandardOutputatau StandardErrorke file:YOUR_ABSPATH_FILENAME. The file:pathopsi didokumentasikan dalam terbaru systemd.exechalaman manual .

Fitur baru ini relatif baru dan tidak tersedia untuk distro lama seperti centos-7 (atau centos sebelumnya).

Trevor Boyd Smith
sumber
10
Tidak bekerja di ubuntu 1604 pada 2018-03-20. Versi systemd di ubuntu 1604 hanya 229.
orang perunggu
Terima kasih, katamu sangat jelas. Saya hanya tidak percaya systemd di ubuntu 1604 tidak bisa mengarahkan output ke file hanya dengan config. Saya harus menggunakan cara sh untuk menyelesaikan masalah ini.
pria perunggu
@bronzeman permintaan fitur tidak ditutup hingga 2017, sementara Ubuntu 16.04 keluar pada 2016. Dalam rilis besar yang diberikan Ubuntu (mis. 16.04, 16.10, 17.04, dll.), Ubuntu mempertahankan kompatibilitas ABI dalam paket sistem intinya. Jadi mereka tidak akan memutakhirkan systemd (atau kernel Linux, atau glibc, atau apa pun) kecuali itu mempertahankan ABI yang sama seperti ketika versi Ubuntu pertama kali dirilis.
villapx
1
FWIW: Saya sudah mencari sedikit tetapi fitur ini tampaknya tidak memiliki ketentuan untuk rotasi log, seperti fungsi untuk membuka kembali file log, dengan yang harus menggunakan suka copytruncatedi logrotate.
antak
48

Anda mungkin mendapatkan kesalahan ini:

Failed to parse output specifier, ignoring: /var/log1.log

Dari systemd.exec(5)halaman manual:

StandardOutput=

Kontrol di mana file descriptor 1 (STDOUT) dari proses yang dieksekusi terhubung. Mengambil salah satu inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+consoleatau socket.

The systemd.exec(5)man page menjelaskan pilihan lain yang terkait dengan penebangan. Lihat juga systemd.service(5)dan systemd.unit(5)manusia halaman.

Atau mungkin Anda dapat mencoba hal-hal seperti ini (semuanya dalam satu baris):

ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log' 
Shuangistan
sumber
7
Di antara opsi, masuk ke jurnal systemd direkomendasikan. Anda hanya melihat log untuk proses Anda di jurnal dengan menggunakan journalctl -u your-unit-name.
Mark Stosberg
6
Untuk menentukan file, ada opsi pembersih lain, seperti yang ditunjukkan oleh dokumentasi:The fd option connects the output stream to a single file descriptor provided by a socket unit. A custom named file descriptor can be specified as part of this option, after a ":" (e.g. "fd:foobar").
orion
5
Jawaban awsome, ini menyelesaikan masalah saya. Aku hanya ingin memperpanjang, karena saat ini jika layanan Restart menimpa lama log, harus mengganti bagian ini: 2>&1 > /var/log.loguntuk ini: 2>&1 >> /var/log.log. Terima kasih
PumpkinSeed
10
Terus terang, memanggil shell dengan string perintah di ExecStart terdengar seperti Cara yang Benar Salah untuk melakukannya.
David Tonhofer
1
"/ bin / sh" adalah solusi yang bagus, tetapi Anda HARUS menggunakan "exec", jika tidak, layanan tidak akan memulai kembali dengan benar karena SIGTERM tidak akan diteruskan ke proses anak. Lihat veithen.io/2014/11/16/sigterm-propagation.html
Kaya
33

Saya akan menyarankan menambahkan stdoutdan stderrfile dalam servicefile systemd itu sendiri.

Merujuk: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

Karena Anda telah mengkonfigurasi, seharusnya tidak suka:

StandardOutput=/home/user/log1.log
StandardError=/home/user/log2.log

Harus:

StandardOutput=file:/home/user/log1.log
StandardError=file:/home/user/log2.log

Ini berfungsi ketika Anda tidak ingin me-restart layanan lagi dan lagi .

Ini akan membuat file baru dan tidak menambahkan file yang ada.

Gunakan Sebaliknya:

StandardOutput=append:/home/user/log1.log
StandardError=append:/home/user/log2.log

CATATAN: Pastikan Anda sudah membuat direktori. Saya kira itu tidak mendukung untuk membuat direktori.

Rajat jain
sumber
5
Gandakan jawaban ini , dengan perincian lebih sedikit
Gert van den Berg
9
Saya pikir, saya membuatnya lebih langsung \ mudah dimengerti.
Rajat jain
1
Bagi saya, file:rute tersebut berfungsi pada beban pertama layanan, tetapi pada restart berikutnya tidak lagi menulis ke file. Saya mencoba append:dari dokumen dan itu tidak berhasil sama sekali.
rb-
3
Perhatikan bahwa dokumen menjelaskan bahwa file:menulis ke awal file setiap kali, dan tidak memotong ... lebih lanjut, append:tampaknya merupakan tambahan baru (yaitu tidak ada pada man systemd.exechalaman di Ubuntu 18.04).
cole
19

Jika karena alasan tertentu tidak dapat menggunakan rsyslog, ini bisa dilakukan: ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"

Tigra
sumber
Apa yang dilakukan opsi -e dari bash?
Lampu
3

Asumsikan log sudah dimasukkan ke stdout / stderr , dan login unit systemd/var/log/syslog

journalctl -u unitxxx.service

Jun 30 13:51:46 host unitxxx[1437]: time="2018-06-30T11:51:46Z" level=info msg="127.0.0.1
Jun 30 15:02:15 host unitxxx[1437]: time="2018-06-30T13:02:15Z" level=info msg="127.0.0.1
Jun 30 15:33:02 host unitxxx[1437]: time="2018-06-30T13:33:02Z" level=info msg="127.0.0.1
Jun 30 15:56:31 host unitxxx[1437]: time="2018-06-30T13:56:31Z" level=info msg="127.0.0.1

Config rsyslog (Layanan Logging Sistem)

# Create directory for log file
mkdir /var/log/unitxxx

# Then add config file /etc/rsyslog.d/unitxxx.conf

if $programname == 'unitxxx' then /var/log/unitxxx/unitxxx.log
& stop

Mulai ulang rsyslog

systemctl restart rsyslog.service
Hieu Huynh
sumber
1

Kami menggunakan Centos7, aplikasi boot musim semi dengan systemd. Saya menjalankan java seperti di bawah ini. dan pengaturan StandardOutput ke file tidak berfungsi untuk saya.

ExecStart=/bin/java -jar xxx.jar  -Xmx512-Xms32M

Solusi penyelesaian di bawah ini berfungsi tanpa menetapkan StandardOutput. menjalankan java melalui sh seperti di bawah ini.


ExecStart=/bin/sh -c 'exec /bin/java -jar xxx.jar -Xmx512M -Xms32M >> /data/logs/xxx.log 2>&1'

masukkan deskripsi gambar di sini

Santhosh Hirekerur
sumber
-1 untuk mendefinisikan parameter jvm dalam urutan yang salah. -Xmx512M harus didefinisikan sebelum -jar. Juga apa yang Anda alami diharapkan. Systemd tidak meminta layanan menggunakan shell
Sami Korhonen
1
@SamiKorhonen, saya menambahkan komentar saya setelah pengujian ini berfungsi. Bahkan saya berpikir tentang urutan -Xmx512M sangat cocok untuk Anda. Silakan uji sebelum menambahkan komentar buta.
Santhosh Hirekerur
0

Jawaban singkat:

StandardOutput=file:/var/log1.log
StandardError=file:/var/log2.log

Jika Anda tidak ingin file dihapus setiap kali layanan dijalankan, gunakan tambahkan saja:

StandardOutput=append:/var/log1.log
StandardError=append:/var/log2.log
Arnett Rufino
sumber
2
Gandakan jawaban ini , dengan detail lebih sedikit
rustyx