Làm cách nào tôi có thể ghi nhật ký quy trình được bắt đầu bởi start-stop-daemon?


120

Tôi đang sử dụng tập lệnh init để chạy một quá trình đơn giản, được bắt đầu bằng:

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

Quá trình được gọi là $ DAEMON thường in thông tin nhật ký ra đầu ra tiêu chuẩn của nó. Theo như tôi có thể nói rằng dữ liệu này không được lưu trữ ở bất cứ đâu.

Tôi muốn viết hoặc nối đoạn mã $ DAEMON vào một tệp ở đâu đó.

Giải pháp duy nhất mà tôi biết là yêu cầu start-stop-daemon gọi shellcript thay vì $ DAEMON trực tiếp; sau đó tập lệnh gọi $ DAEMON và ghi vào logfile. Nhưng điều đó yêu cầu một tập lệnh bổ sung, chẳng hạn như sửa đổi chính daemon, dường như là cách sai để giải quyết một nhiệm vụ phổ biến như vậy.

Câu trả lời:


127

Để mở rộng câu trả lời của ypocat, vì nó sẽ không cho phép tôi bình luận:

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"

Sử dụng execđể chạy daemon cho phép dừng để dừng quá trình con một cách chính xác thay vì chỉ bash cha.

Sử dụng --startasthay vì --execđảm bảo rằng quá trình sẽ được phát hiện chính xác bởi pid của nó và sẽ không bắt đầu sai nhiều phiên bản của daemon nếu khởi động được gọi nhiều lần. Nếu không, start-stop-daemon sẽ tìm kiếm tiến trình / bin / bash và bỏ qua tiến trình con thực sự đang chạy daemon.


2
Đây là một giải pháp tốt hơn nhiều so với giải pháp @ypocat chủ yếu là vì tắt trình nền một lần nữa bằng cách thay thế --startbằng --stopcác hoạt động thực sự.
aef

Tôi đã thử chạy lệnh này từ rc.local thay vì init.d ... Tôi dường như không nhận được kết quả tương tự. Tuy nhiên, khi chạy nó từ shell thông qua SSH, nó hoạt động như một sự quyến rũ!
nemo

1
Đi kèm start-stop-daemon --test (...)sẽ như thế nào?
Abdull

2
@MattClimbs Nó ghi đè lên tệp sau mỗi lần bắt đầu. sử dụng >>thay vì >để bổ sung.
Meo

2
Trước khi bạn phát hoảng (như tôi) vì nhật ký của bạn trống, hãy lưu ý rằng điều này được lưu vào bộ đệm! Bạn có thể sử dụng "execute stdbuf -oL -eL $ DAEMON $ DAEMONARGS> $ LOGFILE 2> & 1" để buộc đầu ra xả từng dòng (từ blog.lanyonm.org/articles/2015/01/11/… )
piers7

47

Bạn cần phải là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"

Ngoài ra, nếu bạn sử dụng --chuidhoặc --user, hãy đảm bảo rằng người dùng có thể ghi vào /var/loghoặc hiện có /var/log/some.log. Cách tốt nhất là để người dùng đó sở hữu /var/log/subdir/mặc dù.


1
Tuyệt vời, cảm ơn bạn ypocat. Hôm nay, cũng như lưu nhật ký, tôi cần chạy một tập lệnh không phải nhị phân --exec không cho phép nhưng thủ thuật của bạn hoạt động hiệu quả!
joeytwiddle 11/10/12

8
Mặt dưới ... ngừng dịch vụ giết chết bash, nhưng không bắt đầu quá trình con bash bash! (Trong trường hợp của tôi, DAEMON = cà phê).
joeytwiddle

1
Tôi đã giải quyết vấn đề đó bằng cách giết tất cả các quy trình con của quy trình bash ở đầu do_stop. bashPID=$(cat $PIDFILE); [ -n "$bashPID" ] && pkill -P "$bashPID"
joeytwiddle

5
Điều tốt để biết, và cả pkillgiải pháp nữa. Tự hỏi những gì sẽ làm ... -c "exec $DAEMON..."(thêm "hành"). Không có món này trên đĩa ngay bây giờ nên không thể thử.
youurayy

12
@ypocat Tôi vừa xác minh rằng nó hoạt động với -c "executive $ DAEMON ...". Điều này có nghĩa là không cần hack pkill.
overthink

40

Có vẻ như bây giờ bạn sẽ có thể sử dụng --no-closetham số này khi bắt đầu bắt đầu start-stop-daemonra daemon. Đây tính năng mới có sẵn trong dpkggói kể từ phiên bản 1.16.5 trên Debian:

Thêm tùy chọn --no-close mới để tắt fds đóng trên --background.

Điều này cho phép người gọi xem các thông báo xử lý cho mục đích gỡ lỗi hoặc có thể chuyển hướng các bộ mô tả tệp sang tệp nhật ký, nhật ký hệ thống hoặc tương tự.


8
Đó là một sự xấu hổ đó là không có sẵn trong Ubuntu 12.04 :(
Leon Radley

Tôi dường như không thể nhận được rằng --no-gần công việc ... đầu ra vẫn đi đến vỏ mà tôi đang thực hiện kịch bản init.d từ :(
stantonk

+1 Hoạt động hoàn hảo trên bộ nén Debian với dịch vụ node.js được daemonized.
speakr

2
@stantonk Có phải bạn cũng chuyển stdout / stderr vào một tệp không? Dòng lệnh hoàn chỉnh trông như sau. Và đảm bảo rằng tệp nhật ký có thể được viết bởi người dùng $ 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
Điều này không có sẵn với openrc start-stop-daemon. Tuy nhiên, phiên bản openrc có -1-2các tùy chọn để chuyển hướng stdout và stderr tương ứng.
little-dude

14

Với openrc (là mặc định trên gentoo hoặc alpine linux chẳng hạn) start-stop-daemoncó các tùy chọn -1-2tùy chọn:

-1, --stdout Chuyển hướng stdout tới tệp

-2, --stderr Chuyển hướng stderr tới tệp

Vì vậy, bạn chỉ có thể viết:

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

9

Không quá khó để nắm bắt đầu ra của daemon và lưu nó vào tệp:

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

Tuy nhiên giải pháp này có thể không tối ưu cho logrotate.

Có thể tốt hơn nếu ghi đầu ra vào nhật ký hệ thống. Trên Debian, điều này sẽ phù hợp với hành vi của các dịch vụ systemd. Nỗ lực đơn giản sau đây để viết lại ví dụ trên là sai vì nó để lại hai tiến trình không cha mẹ ("zombie") (trình ghi và daemon) sau khi dừng daemon vì start-stop-daemonchỉ chấm dứt con của nó chứ không phải tất cả con cháu:

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

Để làm cho nó hoạt động, chúng tôi cần một trình bao bọc kết thúc các con của nó khi nhận được SIGTERMtừstart-stop-daemon . Có vài:

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

Lưu ý: uid=65534là một người dùng nobody.

Ưu điểm : nó hoạt động và tương đối dễ dàng.
Nhược điểm : 4 quy trình (trình giám sát duende, fork của nó với các đặc quyền bị giảm (trình ghi nhật ký), suvà chính daemon); bắt buộc --chroot; Nếu daemon kết thúc ngay lập tức (ví dụ: lệnh không hợp lệ), hãy status_of_proc -p $PIDFILE "$DAEMON" "$NAME"báo cáo là đã bắt đầu thành công.

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

Ưu điểm : 3 quá trình (giám sát daemon, suvà daemon chính nó).
Nhược điểm : Khó quản lý $PIDFILEdo các tùy chọn dòng lệnh của daemon khó hiểu ; Nếu daemon kết thúc ngay lập tức (ví dụ: lệnh không hợp lệ), hãy status_of_proc -p $PIDFILE "$DAEMON" "$NAME"báo cáo là đã bắt đầu thành công.

pipexec ( người chiến thắng ):

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

Ưu điểm : 3 quá trình (giám sát pipexec, loggervà daemon bản thân); Nếu daemon kết thúc ngay lập tức (ví dụ: lệnh không hợp lệ) status_of_proc -p $PIDFILE "$DAEMON" "$NAME"báo cáo chính xác lỗi.
Nhược điểm : không có.

Đây là giải pháp chiến thắng - giải pháp dễ dàng, dễ dàng nhất và dường như đang hoạt động tốt.


7

Thường start-stop-daemonđóng các bộ mô tả tệp tiêu chuẩn khi chạy ở chế độ nền. Từ trang người đàn ông của start-stop-daemon:

-C, --no-close
Không đóng bất kỳ bộ mô tả tệp nào khi buộc daemon vào nền. Được sử dụng cho mục đích gỡ lỗi để xem kết quả quá trình hoặc để chuyển hướng bộ mô tả tệp để ghi lại kết quả quá trình. Chỉ có liên quan khi sử dụng --background.

Điều này đã làm việc cho tôi:

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

4

Trích dẫn một danh sách gửi thư cũ:

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

Một cách dễ dàng - và nếu bạn muốn sử dụng start-stop-daemon thì có lẽ cách duy nhất - là tạo một tập lệnh nhỏ chứa:

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

và sau đó sử dụng tập lệnh đó làm đối số cho start-stop-daemon.

Tuy nhiên, có lẽ câu hỏi thực sự là liệu nó có thực sự cần thiết để sử dụng start-stop-daemon ngay từ đầu hay không?


3

Tôi không chắc liệu "$ DAEMON $ DAEMON_ARGS> /var/log/some.log 2> & 1" có bao giờ đóng trình mô tả tệp cho tệp nhật ký hay không ... có nghĩa là nếu daemon của bạn chạy mãi mãi, tôi không chắc logrotate hoặc các cơ chế khác để dọn dẹp không gian đĩa sẽ hoạt động. Vì nó> thay vì >>, lệnh được đề xuất cũng sẽ cắt bớt nhật ký hiện có khi khởi động lại. Nếu bạn muốn biết lý do tại sao daemon bị lỗi và nó tự động khởi động lại, điều đó có thể không hữu ích lắm.

Một tùy chọn khác có thể là "$ DAEMON | logger". logger là một lệnh sẽ đăng nhập vào nhật ký hệ thống (/ var / log / messages). Nếu bạn cũng cần stderr, tôi nghĩ bạn có thể sử dụng "$ DAEMON 1> & 2 | logger"


Bạn nói đúng, việc sử dụng >>thường thích hợp hơn cho daemon, mặc dù nó ngụ ý rằng bây giờ bạn nên tạo một quy tắc logrotate!
joeytwiddle

Đối với không gian đĩa, các phương thức cắt bớt tệp sẽ lấy lại không gian ngay lập tức (ít nhất là trong hệ thống tệp ext). Nhưng hãy cẩn thận với các phương pháp chỉ xóa một tệp vẫn đang được ghi vào: không gian sẽ không được lấy lại cho đến khi xử lý được giải phóng và bạn không còn có thể tìm thấy nút tệp để cắt nó theo cách thủ công!
joeytwiddle

@joeytwiddle một phần quan điểm của tôi ở đây là có những tình huống mà logrotate sẽ không thể xoay nhật ký nếu xử lý tệp không bao giờ được đóng.
nairbv

--no-close ... | loggerkhông hoạt động đối với tôi (Debian 7.3, start-stop-daemon 1.16.12). Tập lệnh start-stop-daemon không quay trở lại, mặc dù / var / log / messages đã được điền :-). Tôi đã thử nó có và không 1>&2.
hgoebl

hgoebl bạn cần có biểu thức "cmd | logger" trong dấu ngoặc kép, vì vậy trình thông dịch sẽ biết đó là "cmd" bạn đang chuyển tới trình ghi, không phải biểu thức start-stop-daemon.
Wexxor

2

Giả sử nó bash (mặc dù một số shell khác cũng có thể cho phép điều này), dòng:

exec >>/tmp/myDaemon.log

sẽ gửi tất cả đầu ra tiêu chuẩn trong tương lai tới tệp đó. Đó là bởi vì execkhông có tên chương trình chỉ thực hiện một số phép thuật chuyển hướng. Từ bashtrang người đàn ông:

Nếu lệnh không được chỉ định, mọi chuyển hướng sẽ có hiệu lực trong trình bao hiện tại.

Tất nhiên, việc quản lý tệp đã nói là một vấn đề khác.


bạn có thể làm rõ nơi dòng này được cho là được đặt? Ngay sau start-stop-daemondòng mà câu hỏi ban đầu đề cập đến?
Abdull

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.