Systemd hizmetinin çıktısını bir dosyaya yeniden yönlendirme


171

Bir systemdhizmetin çıktısını bir dosyaya yönlendirmeye çalışıyorum ama işe yaramıyor:

[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

Lütfen yaklaşımımı düzeltin.

Yanıtlar:


234

Sorunu çözmenin daha zarif bir yolu olduğunu düşünüyorum: stdout / stderr'ı bir tanımlayıcı ile syslog'a gönderin ve syslog yöneticinize çıktısını program adına göre bölmesini söyleyin.

Systemd hizmet birimi dosyanızda aşağıdaki özellikleri kullanın:

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

Ardından, dağıtımınızın syslog'ları yönetmek için rsyslog kullandığını varsayarsak /etc/rsyslog.d/<new_file>.conf, aşağıdaki içeriğe sahip bir dosya oluşturun :

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

Şimdi günlük dosyasını syslog tarafından yazılabilir yapın:

# 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

Rsyslog ( sudo systemctl restart rsyslog) 'u yeniden başlatın ve tadını çıkarın! Stdout / stderr programınıza yine journalctl ( sudo journalctl -u <your program identifier>) aracılığıyla erişilebilir, ancak bunlar seçtiğiniz dosyada da kullanılabilir.

Kaynak archive.org üzerinden


8
Ubuntu 16.04'te benim için çalışmıyor. journalctl -uhala çalışıyor ancak belirtilen dosyaya hiçbir şey gönderilmiyor.
Duncan Calvert

1
Bu, Debian streç üzerinde harika çalışıyor, ancak ~kullanımdan kaldırıldığından ve stopbunun yerine kullanılması gerektiğinden şikayet ediyor . Ayrıca & stop, ikisinin birbiri ardına gelmesi durumunda ikinci satırın kısaltılabileceğini de unutmayın .
jlh

48
Systemd 236 veya daha yeni bir sürümle,
leezu

5
/etc/rsyslog.d/<newfile>.confİçeriği şu şekilde değiştirerek :programname, isequal, "<your program identifier>" /var/log/somelog.log çalıştım : İşte rsyslog filtreleriyle ilgili belgeler: rsyslog.com/doc/v8-stable/configuration/filters.html Ve işte dokümanlar şöyleprogramname : rsyslog.com/doc/master/configuration/properties .html
mbil

1
Ben rsyslogkendi kullanıcı syslogve günlükleri konuma yazma erişimi olması gereken bulana kadar bu yapılandırmayı kullanarak sorun vardı . Bu yüzden chownuygun şekilde kullanın . Umarım bu birine yardımcı olur.
Imaskar

73

Eğer daha yeni daha yeni bir dağıtımın varsa systemd( systemdsürümüne 236 veya daha yeni ) kullanarak, değerlerini ayarlayabilir StandardOutputveya StandardErrorhiç file:YOUR_ABSPATH_FILENAME.


Uzun Hikaye:

Daha yeni sürümlerinde systemdnispeten yeni bir seçenek yoktur ( github isteği 2016 den imsi ve geliştirme / birleşti 2017 ISH kapalıdır ) Eğer değerlerini ayarlayabilirsiniz nerede StandardOutputya StandardErrorkadar file:YOUR_ABSPATH_FILENAME. file:pathSeçenek belgelenmiştir En son systemd.execadam sayfası .

Bu yeni özellik nispeten yenidir ve bu nedenle centos-7 (veya ondan önceki herhangi bir centos) gibi eski dağıtımlar için mevcut değildir.


10
2018-03-20'de Ubuntu 1604'te çalışmıyor. Ubuntu 1604'teki sistemd sürümü sadece 229'dur.
bronz adam

Teşekkürler, çok açık dedin. Ben sadece ubuntu 1604 içinde systemd sadece config tarafından bir dosyaya yönlendirme olamaz inanamıyorum. Bu sorunu çözmek için sh yolu kullanmak zorunda.
bronz adam

@bronzeman özellik isteği 2017'ye kadar kapanmadı, Ubuntu 16.04 2016'da çıktı. Ubuntu'nun belirli bir büyük sürümünde (örn. 16.04, 16.10, 17.04, vb.) Ubuntu, temel sistem paketlerinde ABI uyumluluğunu sürdürüyor. Bu nedenle, Ubuntu sürümünün ilk yayınlandığı zamanla aynı ABI'yi korumadıkça systemd'yi (veya Linux çekirdeğini veya glibc'yi veya herhangi bir şeyi) yükseltmezler.
villapx

1
FWIW: Biraz aradık ancak bu özellik gibileri kullanmak zorunda biriyle, böyle günlük dosyasını yeniden açmak için fonksiyon olarak günlük rotasyon için hükümler bulunan görünmüyor copytruncateiçinde logrotate.
antak

49

Muhtemelen bu hatayı alıyorsunuz:

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

Gönderen systemd.exec(5)adam sayfası:

StandardOutput=

Yürütülen işlemlerin dosya tanımlayıcı 1'inin (STDOUT) nereye bağlandığını denetler. Birini Alır inherit, null, tty, journal, syslog, kmsg, journal+console, syslog+console, kmsg+consoleveya socket.

systemd.exec(5)Adam sayfa günlük ilişkin diğer seçenekleri açıklar. Ayrıca systemd.service(5)ve systemd.unit(5)man sayfalarına bakınız.

Ya da belki böyle şeyler deneyebilirsiniz (hepsi bir satırda):

ExecStart=/bin/sh -c '/usr/local/bin/binary1 agent -config-dir /etc/sample.d/server 2>&1 > /var/log.log' 

7
Seçenekler arasında, systemd günlüğüne giriş yapmanız önerilir. Kullanarak yalnızca günlükteki işlemlerin günlüklerini görüntülersiniz journalctl -u your-unit-name.
Mark Stosberg

6
Bir dosya belirtmek için, dokümantasyonda belirtildiği gibi başka bir temizleyici seçenek daha vardır: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
Şaşırtıcı bir cevap, sorunumu çözdü. : Ben sadece hizmet eski günlükleri üzerine yeniden başlatmak anda bile, bu bölümü değiştirmek zorunda çünkü uzatmak istiyorum 2>&1 > /var/log.logbuna: 2>&1 >> /var/log.log. Thank you
PumpkinSeed

10
Açıkçası, ExecStart'ta bir komut dizesiyle kabuk çağırmak, bunu yapmak için Gerçekten Yanlış Yol gibi geliyor.
David Tonhofer

1
"/ bin / sh" harika bir çözümdür, ancak "exec" kullanmanız GEREKİR, aksi takdirde SIGTERM alt işleme geçirilmeyeceğinden hizmet düzgün şekilde yeniden başlamaz. Bkz. Veithen.io/2014/11/16/sigterm-propagation.html
Zengin

33

Systemd dosyasında ekleme stdoutve stderrdosya önerebilirim service.

Yönlendiren: https://www.freedesktop.org/software/systemd/man/systemd.exec.html#StandardOutput=

Yapılandırdığınız için aşağıdaki gibi olmamalıdır:

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

Olmalı:

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

Bu, hizmeti tekrar tekrar başlatmak istemediğinizde çalışır .

Bu yeni bir dosya oluşturur ve mevcut dosyaya eklenmez.

Bunun yerine kullanın:

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

NOT: Dizini zaten oluşturduğunuzdan emin olun. Sanırım bir dizin oluşturmayı desteklemiyor.


5
Kopyası Bu cevap daha az ayrıntılarla birlikte
Gert van Berg den

9
Bence, onu daha doğrudan \ kolay anlaşılır yaptım.
Rajat jain

1
Benim için file:rota, hizmetin ilk yüklemesinde çalışır, ancak sonraki yeniden başlatmalarda artık dosyaya yazmaz. append:Belgelerden denedim ve bu işe yaramadı.
rb-

3
Dokümanların file: her seferinde dosyanın başlangıcına yazıldığını ve kısaltılmadığını ... daha fazla, append:yeni bir ek gibi görünüyor (yani man systemd.execUbuntu 18.04'teki sayfada mevcut değil ).
cole

19

Herhangi bir nedenden dolayı rsyslog kullanamıyorsanız, aşağıdakileri yapar: ExecStart=/bin/bash -ce "exec /usr/local/bin/binary1 agent -config-dir /etc/sample.d/server >> /var/log/agent.log 2>&1"


Bash'nin -e seçeneği ne işe yarar?
Lamba

3

Günlüklerin zaten stdout / stderr'e konulduğunu varsayın ve systemd biriminin oturum açmış olduğunu/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

Rsyslog yapılandır (Sistem Günlüğü Hizmeti)

# 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

Rsyslog'u yeniden başlat

systemctl restart rsyslog.service

1

Systemd ile Centos7, yay çizme uygulamasını kullanıyoruz. Java'yı aşağıdaki gibi çalıştırıyordum. ve StandardOutput'u dosyaya ayarlamak benim için çalışmadı.

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

Aşağıdaki geçici çözüm StandardOutput'u ayarlamadan çalışır. java sh ile aşağıdaki gibi çalışıyor.


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

resim açıklamasını buraya girin


Jvm parametrelerini yanlış sırayla tanımlamak için -1. -Xmx512M, -jar'dan önce tanımlanmalıdır. Ayrıca deneyimleriniz de bekleniyor. Systemd kabuk kullanarak hizmet çağırmıyor
Sami Korhonen

1
@SamiKorhonen, bunun işe yaradığını test ettikten sonra yorumlarımı ekledim. -Xmx512M'nin siparişinin bile size gülümsediğini düşünüyordum. Kör yorumlar eklemeden önce lütfen test edin.
Santhosh Hirekerur

0

Kısa cevap:

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

Hizmet her çalıştırıldığında dosyaların silinmesini istemiyorsanız bunun yerine append komutunu kullanın:

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

2
Kopyası Bu cevap daha az ayrıntılarla birlikte
rustyx
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.