Start-stop-daemon tarafından başlatılan bir sürecin stdout'unu nasıl günlüğe kaydedebilirim?


120

Aşağıdakilerle başlayan basit bir işlemi çalıştırmak için bir init betiği kullanıyorum:

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

$ DAEMON adlı süreç genellikle günlük bilgilerini standart çıktısına yazdırır. Anladığım kadarıyla bu veriler hiçbir yerde saklanmıyor.

$ DAEMON'un stdout'unu bir yerde bir dosyaya yazmak veya eklemek istiyorum.

Bildiğim tek çözüm, start-stop-daemon'a doğrudan $ DAEMON yerine bir shellscript çağırmasını söylemektir; komut dosyası daha sonra $ DAEMON'u çağırır ve günlük dosyasına yazar. Ancak bu, arka plan programının kendisini değiştirmek gibi, bu kadar yaygın bir görevi çözmenin yanlış yolu gibi görünen fazladan bir komut dosyası gerektirir.

Yanıtlar:


127

Yorum yapmama izin vermeyeceği için ypocat'ın cevabını genişletmek için:

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"

execArka plan programını çalıştırmak için kullanmak , durdurmanın sadece ana bash yerine alt süreci doğru şekilde durdurmasını sağlar.

--startasBunun yerine kullanmak --exec, işlemin kendi pid'i tarafından doğru bir şekilde algılanmasını ve start birden çok kez çağrılırsa arka plan programının birden çok örneğini yanlışlıkla başlatmamasını sağlar. Aksi takdirde, start-stop-daemon bir / bin / bash sürecini arar ve arka plan programını çalıştıran asıl çocuk süreci yok sayar.


2
Bu, @ypocat çözümünden çok daha iyi bir çözümdür çünkü aslında işe yarayan --startile değiştirerek daemon'u tekrar kapatmaktır --stop.
aef

Bu komutu init.d yerine rc.local'dan çalıştırmayı denedim ... Aynı sonuçları almıyorum. Ancak, onu bir kabuktan SSH aracılığıyla çalıştırırken bir cazibe gibi çalışır!
nemo

1
Eşlik eden nasıl start-stop-daemon --test (...)görünecek?
Abdull

2
@MattClimbs Her başlatmadan sonra dosyanın üzerine yazar. eklemek >>yerine kullanın >.
Miyav

2
Günlüğünüz boş olduğu için çıldırmadan önce (benim gibi), bunun arabelleğe alındığını unutmayın! Çıktıyı her satırı temizlemeye zorlamak için "exec stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2> & 1" kullanabilirsiniz ( blog.lanyonm.org/articles/2015/01/11/… adresinden )
piers7

47

Yapman lazım:

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"

Ayrıca --chuidveya kullanıyorsanız --user, kullanıcının /var/logveya var olana yazabildiğinden emin olun /var/log/some.log. En iyi yol, o kullanıcının bir /var/log/subdir/düşünceye sahip olmasıdır .


1
Harika, teşekkürler ypocat. Bugün, günlüğü kaydetmenin yanı sıra, ikili olmayan bir komut dosyası çalıştırmam gerekiyordu, --exec buna izin vermiyor, ancak numaranız işe yarıyor!
joeytwiddle

8
Kötü tarafı ... hizmeti durdurmak bash'ı öldürür, ancak alt süreç bash başlamadı! (Benim durumumda DAEMON = kahve).
joeytwiddle

1
Do_stop'un üst kısmında bash sürecinin tüm alt süreçlerini öldürerek bunun etrafında çalıştım. bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
joeytwiddle

5
Bilmekte fayda var ve pkillçözüm de. Ne yapacağını merak ediyorum ... -c "exec $DAEMON..."("exec" ekleyerek). Bunu şu anda tabakta bulundurmayın, bu yüzden deneyemezsiniz.
youurayy

12
@ypocat -c "exec $ DAEMON ..." ile çalıştığını doğruladım. Bu, hiçbir pkill hackine gerek olmadığı anlamına gelir.
overthink

40

Görünüşe göre şimdi kullanabilmelisiniz --no-closestart-stop-daemon arka plan programı çıktısını yakalamaya başlarken parametreyi . Bu yeni özellik mevcuttur dpkgDebian sürümü 1.16.5 beri paketin:

--Background üzerinde fds kapatmayı devre dışı bırakmak için yeni --no-close seçeneği ekleyin.

Bu, arayanın hata ayıklama amacıyla işlem mesajlarını görmesini veya dosya tanımlayıcılarını günlük dosyalarına, syslog veya benzerlerine yeniden yönlendirebilmesini sağladı.


8
Ubuntu 12.04'te mevcut olmaması çok yazık :(
Leon Radley

Bunu
anlayamıyorum

+1 daemonize edilmiş bir node.js hizmetiyle Debian sıkıştırmasında mükemmel çalışır.
talkr

2
@stantonk stdout / stderr'i bir dosyaya da aktartınız mı? Komuta satırının tamamı aşağıdaki gibi görünür. Ve günlük dosyasının $ USER kullanıcısı tarafından yazılabileceğinden emin olun: start-stop-daemon --start --chuid $ USER --pidfile $ PIDFILE --background --no-close --make-pidfile --exec $ DAEMON - $ DAEMONARGS >> /var/log/xxxxx.log 2> & 1
nharrer

1
Bu openrc ile mevcut değildir start-stop-daemon. Ancak openrc sürümü, sırasıyla stdout ve stderr'i yeniden yönlendirmek için -1ve -2seçeneklerine sahiptir.
küçük dostum

14

(Gentoo veya örneğin alp linux üzerinde varsayılan) openrc ile start-stop-daemonvardır -1ve -2seçenekleri:

-1, --stdout Stdout'u dosyaya yönlendir

-2, --stderr Stderr dosyasını dosyaya yönlendir

Yani yazabilirsiniz:

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

9

Arka planın çıktısını yakalamak ve bir dosyaya kaydetmek çok zor değildir:

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

Ancak bu çözüm yetersiz olabilir logrotate.

Syslog'a çıktı almak daha iyi olabilir. On Debian bu systemd hizmetlerin davranışını eşleşir. Yukarıdaki örneği yeniden yazmak için yapılan aşağıdaki doğrudan girişim yanlıştır çünkü arka plan programı durdurulduktan sonra ardında iki ebeveyn olmayan ("zombi") işlemi (günlükçü ve arka plan programı) bırakır, çünkü start-stop-daemonyalnızca alt öğelerini sonlandırır, ancak tüm soyundan gelenleri değil:

## 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"""

Çalışmasını sağlamak için, çocuklarını alınınca sonlandıran bir paketleyiciye ihtiyacımız var SIGTERM.start-stop-daemon . Biraz var:

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"""

Not: uid=65534bir kullanıcıdırnobody .

Artıları : işe yarıyor ve nispeten kolay.
Eksileri : 4 işlem (süpervizör duende, bırakılan ayrıcalıklara sahip çatalı (logger) suve arka plan programının kendisi); zorunlu --chroot; Arka plan programı hemen sona ererse (örneğin geçersiz komut)status_of_proc -p $PIDFILE "$DAEMON" "$NAME" , başarıyla başlatıldığını bildirin.

arka plan programı :
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"""

Avantaj : 3 işlemleri (danışman daemon, suve kendisi programı).
Eksileri : Arka plan programının komut satırı seçeneklerinin $PIDFILEkafa karıştırıcı olması nedeniyle yönetilmesi zordur ; Arka plan programı hemen sona ererse (örneğin geçersiz komut)status_of_proc -p $PIDFILE "$DAEMON" "$NAME" , başarıyla başlatıldığını bildirin.

pipexec ( kazanan ):

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}'

Avantaj : 3 işlemleri (danışman pipexec, loggerve kendisi programı); Arka plan programı hemen sonlanırsa (örn. Geçersiz komut), status_of_proc -p $PIDFILE "$DAEMON" "$NAME"hatayı doğru şekilde bildirin.
Eksileri : yok.

Bu kazanan - iyi çalışıyor gibi görünen en kolay, temiz çözüm.


7

start-stop-daemonArka planda çalışırken genellikle standart dosya tanımlayıcılarını kapatır. Man sayfasından start-stop-daemon:

-C, --no-close
Artalan sürecini arka plana zorlarken hiçbir dosya tanımlayıcısını kapatmayın. İşlem çıktısını görmek için hata ayıklama amacıyla veya işlem çıktısını günlüğe kaydetmek için dosya tanımlayıcılarını yeniden yönlendirmek için kullanılır. Yalnızca --background kullanılırken geçerlidir.

Bu benim için çalıştı:

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

4

Eski bir posta listesinden alıntı yapmak:

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

Kolay bir - ve eğer start-stop-arka plan programını kullanmak istiyorsanız belki de tek yolu - aşağıdakileri içeren küçük bir betik oluşturmaktır:

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

ve sonra bu betiği arka plan programı başlatmak için argüman olarak kullanın.

Belki de asıl soru başlangıçta start-stop-daemon kullanmanın gerçekten gerekli olup olmadığıdır?


3

"$ DAEMON $ DAEMON_ARGS> /var/log/some.log 2> & 1" nin günlük dosyası için dosya tanımlayıcısını kapatacağından emin değilim ... yani arka plan programınız sonsuza kadar çalışıyorsa, emin değilim disk alanını temizlemek için logrotate veya diğer mekanizmalar çalışacaktır. >> yerine> olduğundan, önerilen komut yeniden başlatıldığında mevcut günlükleri de kesecektir. Arka plan programının neden çöktüğünü görmek istiyorsanız ve otomatik olarak yeniden başlatılırsa, bu çok yardımcı olmayabilir.

Diğer bir seçenek "$ DAEMON | logger" olabilir. logger, syslog (/ var / log / messages) için günlük kaydı yapacak bir komuttur. Stderr'e de ihtiyacınız varsa, "$ DAEMON 1> & 2 | logger" kullanabilirsiniz.


Haklısınız, kullanmak >>genellikle arka plan yordamları için daha uygundur, ancak şimdi bir logrotate kuralı oluşturmanız gerektiği anlamına gelir!
joeytwiddle

Disk alanına gelince , dosyayı kesen yöntemler alanı hemen geri alacaktır (en azından ext dosya sistemleri altında). Ancak , hala yazılmakta olan bir dosyayı silen yöntemlere dikkat edin : alan, tutamaç serbest bırakılıncaya kadar geri alınmayacaktır ve artık onu manuel olarak kesmek için dosya düğümünü bulamazsınız!
joeytwiddle

@joeytwiddle buradaki amacımın bir kısmı, logrotate'in dosya tanıtıcısı asla kapatılmadığı takdirde günlükleri döndüremeyeceği durumlar olmasıdır.
nairbv

--no-close ... | loggerbenim için çalışmıyor (Debian 7.3, start-stop-daemon 1.16.12). Start-stop-daemon betiği / var / log / messages doldurulsa da geri gelmez :-). Olsa da olmasa da denedim 1>&2.
hgoebl

hgoebl, tırnak içinde "cmd | logger" ifadesine sahip olmanız gerekir, böylece yorumlayıcı, start-stop-daemon ifadesi değil, "cmd" olarak logger'a bağlandığınızı bilecektir.
Wexxor

2

Bash olduğunu varsayarsak (diğer bazı kabuklar da buna izin verse de), satır:

exec >>/tmp/myDaemon.log

gelecekteki tüm standart çıktıları o dosyaya gönderir. Bunun nedeni exec, bir program adı olmadan sadece yeniden yönlendirme sihri oluşturmasıdır. Gönderen bashadam sayfası:

Komut belirtilmezse, mevcut kabukta herhangi bir yeniden yönlendirme etkili olur.

Söz konusu dosyanın yönetimi elbette ayrı bir konudur.


Bu çizginin nereye yerleştirileceğini açıklayabilir misin? start-stop-daemonİlk sorunun bahsettiği satırdan hemen sonra ?
Abdull

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.