[perl] 유닉스에서 임의의 스크립트를 어떻게 데몬 화합니까?

임의의 일반 스크립트 또는 명령을 데몬 으로 바꿀 수있는 데몬 라이저를 원합니다 .

처리하고 싶은 두 가지 일반적인 경우가 있습니다.

  1. 영원히 실행되어야하는 스크립트가 있습니다. 죽는 경우 (또는 재부팅시) 다시 시작하십시오. 한 번에 두 개의 복사본이 실행되도록하지 마십시오 (복제가 이미 실행 중인지 감지하고이 경우 실행하지 마십시오).

  2. 영원히 반복적으로 실행하고 싶은 간단한 스크립트 또는 명령 줄 명령이 있습니다 (실행 사이에 잠시 멈춤). 다시 말하지만, 두 개의 스크립트 사본이 한 번에 실행되는 것을 허용하지 마십시오.

물론 사례 2의 경우 스크립트 주위에 “while (true)”루프를 작성한 다음 사례 1에 대한 솔루션을 적용하는 것은 간단하지만보다 일반적인 솔루션은 사례 1의 스크립트에 다음과 같이 적용되므로 사례 2를 직접 해결합니다. 잘 (스크립트가 정말 경우 스크립트가 이제까지 물론 (다이에 구성되지 않은 경우 그냥 짧은 또는 전혀 일시 정지를 할 수 있습니다 않고 다음 죽지 않을 일시 정지하지 않습니다 실제로 문제)).

솔루션은 기존 스크립트에 파일 잠금 코드 또는 PID 기록을 추가하는 것과 관련이 없어야합니다.

좀 더 구체적으로 말하자면, 다음과 같이 실행할 수있는 “daemonize”프로그램을 원합니다.

% daemonize myscript arg1 arg2

또는 예를 들어

% daemonize 'echo `date` >> /tmp/times.txt'

이는 times.txt에 추가 된 날짜 목록을 계속 유지합니다. (데몬화할 인수가 위의 경우 1과 같이 영원히 실행되는 스크립트 인 경우 데몬 이즈는 여전히 올바른 작업을 수행하고 필요할 때 다시 시작합니다.) 그런 다음 .login에 위와 같은 명령을 넣을 수 있습니다. 및 / 또는 시간 또는 분 단위로 cron (예기치 않게 죽어가는 것에 대해 얼마나 걱정했는지에 따라 다름).

주의 : daemonize 스크립트는 데몬 화중인 명령 문자열을 기억해야합니다. 그래야 동일한 명령 문자열이 다시 데몬 화되는 경우 두 번째 복사본이 시작되지 않습니다.

또한 솔루션은 OS X와 ​​Linux 모두에서 이상적으로 작동해야하지만 둘 중 하나에 대한 솔루션도 환영합니다.

편집 : 당신이 그것을 호출 해야하는 경우 괜찮습니다 sudo daemonize myscript myargs.

(내가이 모든 것을 잘못 생각하고 있거나 빠르고 더러운 부분적인 해결책이 있다면, 저도 듣고 싶습니다.)


추신 : 유용하다면 여기 에 파이썬과 관련된 비슷한 질문이 있습니다.

그리고 유사한 질문에 대한 답변에는 임의의 스크립트를 빠르고 더러운 데몬 화하는 데 유용한 관용구가 있습니다.



답변

nohup 및 & 연산자를 사용하여 Unix의 모든 실행 파일을 데몬화할 수 있습니다.

nohup yourScript.sh script args&

nohup 명령을 사용하면 스크립트를 종료하지 않고 셸 세션을 종료 할 수 있으며 &는 스크립트를 백그라운드에 배치하여 세션을 계속하라는 셸 프롬프트를 표시합니다. 이것에 대한 유일한 사소한 문제는 표준 출력이고 표준 오류는 모두 ./nohup.out으로 전송되므로이 매너에서 여러 스크립트를 시작하면 출력이 서로 얽혀 있습니다. 더 나은 명령은 다음과 같습니다.

nohup yourScript.sh script args >script.out 2>script.error&

그러면 선택한 파일로 표준이 전송되고 선택한 다른 파일로 표준 오류가 전송됩니다. 표준 출력 및 표준 오류에 대해 하나의 파일 만 사용하려면 다음을 수행 할 수 있습니다.

nohup yourScript.sh script args >script.out 2>&1 &

2> & 1은 표준 오류 (파일 설명자 2)를 표준 출력 (파일 설명자 1)과 동일한 파일로 리디렉션하도록 쉘에 지시합니다.

명령을 한 번만 실행하고 죽으면 다시 시작하려면 다음 스크립트를 사용할 수 있습니다.

#!/bin/bash

if [[ $# < 1 ]]; then
    echo "Name of pid file not given."
    exit
fi

# Get the pid file's name.
PIDFILE=$1
shift

if [[ $# < 1 ]]; then
    echo "No command given."
    exit
fi

echo "Checking pid in file $PIDFILE."

#Check to see if process running.
PID=$(cat $PIDFILE 2>/dev/null)
if [[ $? = 0 ]]; then
    ps -p $PID >/dev/null 2>&1
    if [[ $? = 0 ]]; then
        echo "Command $1 already running."
        exit
    fi
fi

# Write our pid to file.
echo $$ >$PIDFILE

# Get command.
COMMAND=$1
shift

# Run command until we're killed.
while true; do
    $COMMAND "$@"
    sleep 10 # if command dies immediately, don't go into un-ctrl-c-able loop
done

첫 번째 인수는 사용할 pid 파일의 이름입니다. 두 번째 인수는 명령입니다. 그리고 다른 모든 인수는 명령의 인수입니다.

이 스크립트의 이름을 restart.sh로 지정하면 다음과 같이 호출 할 수 있습니다.

nohup restart.sh pidFileName yourScript.sh script args >script.out 2>&1 &


답변

긴 답변에 대해 사과드립니다 (내 답변이 사양을 어떻게 결정하는지에 대한 의견을 참조하십시오). 나는 포괄적이려고 노력하고 있으므로 가능한 한 다리를 잘 올리십시오. 🙂

프로그램을 설치할 수 있고 (루트 액세스 권한이 있음) 데몬 실행을 위해 스크립트를 설정하기 위해 일회성 작업을 기꺼이 수행하려는 경우 (즉, 명령 줄에서 실행할 명령 줄 인수를 지정하는 것보다 더 복잡합니다. 하지만 서비스 당 한 번만 수행하면됩니다.) 더 강력한 방법이 있습니다.

daemontools 사용이 포함됩니다 . 나머지 게시물에서는 daemontools를 사용하여 서비스를 설정하는 방법을 설명합니다.

초기 설정

  1. daemontools를 설치하는 방법 의 지침을 따릅니다 . 일부 배포판 (예 : Debian, Ubuntu)에는 이미 패키지가 있으므로 사용하십시오.
  2. 라는 디렉토리를 만듭니다 /service. 설치 프로그램이 이미이 작업을 수행 했어야하지만 확인 만하거나 수동으로 설치하는 경우입니다. 이 위치가 마음에 들지 않으면 svscanboot스크립트 에서 변경할 수 있지만 대부분의 daemontools 사용자는/service 하지 않으면 혼란스러워집니다.
  3. 표준을 사용하지 않는 Ubuntu 또는 다른 배포판을 사용하는 경우 init(예 :를 사용하지 않음 /etc/inittab)에서 호출 inittab할 정렬 svscanboot을 위한 기본으로 사전 설치된을 사용해야합니다 init. 어렵지는 않지만 initOS에서 사용하는 구성 방법을 알아야 합니다.
    서비스를 찾는 주요 작업을 수행 svscanboot하는를 호출하는 스크립트입니다 svscan. 어떤 이유로 든 죽으면 다시 시작 init하도록 에서 호출됩니다 init.

서비스 별 설정

  1. 각 서비스에는 서비스 에 대한 하우스 키핑 정보를 저장 하는 서비스 디렉토리 가 필요합니다 . 또한 이러한 서비스 디렉토리를 보관할 위치를 만들어 모두 한곳에 보관할 수 있습니다. 일반적으로를 사용 /var/lib/svscan하지만 새로운 위치는 괜찮습니다.
  2. 저는 보통 스크립트 를 사용 하여 서비스 디렉토리를 설정하고 많은 수동 반복 작업을 저장합니다. 예 :

    sudo mkservice -d /var/lib/svscan/some-service-name -l -u user -L loguser "command line here"

    여기서는 some-service-name서비스에 제공 할 이름, user해당 서비스 loguser를 실행할 사용자, 로거를 실행할 사용자입니다. (로깅은 조금만 설명합니다.)

  3. 서비스는 포 그라운드에서 실행 되어야합니다 . 프로그램이 기본적으로 배경이지만 비활성화 할 수있는 옵션이 있으면 그렇게하십시오. 프로그램이 비활성화 할 방법없이 배경이있는 경우 fghack에는 절충안이 있더라도을 읽어보십시오 . 더 이상을 사용하여 프로그램을 제어 할 수 없습니다 svc.
  4. 편집 run스크립트를 원하는 작업을 수행하는지 확인하십시오. sleep서비스가 자주 종료 될 것으로 예상되는 경우 맨 위에 전화 를 걸어야 할 수도 있습니다 .
  5. 모든 것이 올바르게 설정되면 /service서비스 디렉토리 를 가리키는 심볼릭 링크를 만듭니다 . (서비스 디렉토리를 내부에 직접 넣지 마십시오 .의 감시 /service에서 서비스를 제거하기가 더 어려워집니다 svscan.)

벌채 반출

  1. daemontools 로깅 방법은 서비스가 로그 메시지를 표준 출력 (또는로 생성 된 스크립트를 사용하는 경우 표준 오류 mkservice)에 기록하도록하는 것입니다. svscan로그 메시지를 로깅 서비스로 보내는 작업을 처리합니다.
  2. 로깅 서비스는 표준 입력에서 로그 메시지를 가져옵니다. 에서 생성 한 로깅 서비스 스크립트 mkservicelog/main디렉토리에 자동 회전 된 타임 스탬프 로그 파일을 생성합니다 . 현재 로그 파일은라고 current합니다.
  3. 로깅 서비스는 기본 서비스와 독립적으로 시작 및 중지 할 수 있습니다.
  4. 로그 파일을 파이핑하면 tai64nlocal타임 스탬프가 사람이 읽을 수있는 형식으로 변환됩니다. (TAI64N은 나노초 카운트의 64 비트 원자 타임 스탬프입니다.)

제어 서비스

  1. svstat서비스 상태를 가져 오는 데 사용 합니다. 로깅 서비스는 독립적이며 자체 상태가 있습니다.
  2. 을 사용하여 서비스 (시작, 중지, 다시 시작 등)를 제어합니다 svc. 예를 들어 서비스를 다시 시작하려면 svc -t /service/some-service-name; -t“보내기 SIGTERM“를 의미합니다 .
  3. 사용 가능한 기타 신호에는 -h( SIGHUP), -a( SIGALRM), -1( SIGUSR1), -2( SIGUSR2) 및 -k(SIGKILL )가 있습니다.
  4. 서비스를 중단하려면을 사용하십시오 -d. 또한 다음과 같은 파일을 생성하여 부팅시 서비스가 자동으로 시작되지 않도록 할 수 있습니다.down서비스 디렉토리에 .
  5. 서비스를 시작하려면 -u . 이전에 다운 (또는 자동 시작하지 않도록 설정)하지 않은 경우에는 필요하지 않습니다.
  6. 감독자에게 종료를 요청하려면 -x; 일반적으로 -d서비스를 종료 하는데도 사용됩니다 . 이는 서비스를 제거 할 수있는 일반적인 방법이지만 /service먼저 서비스 연결을 해제해야합니다 svscan. 그렇지 않으면 수퍼바이저를 다시 시작합니다. 또한 로깅 서비스 ( mkservice -l)를 사용하여 서비스를 생성 한 경우 svc -dx /var/lib/svscan/some-service-name/log서비스 디렉토리를 제거하기 전에 로깅 감독자 (예 :)도 종료해야합니다 .

요약

장점 :

  1. daemontools는 서비스를 만들고 관리하는 방탄 방법을 제공합니다. 내 서버에 사용하고 있으며 적극 권장합니다.
  2. 로깅 시스템은 서비스 자동 재시작 기능과 마찬가지로 매우 강력합니다.
  3. 작성 / 조정하는 셸 스크립트로 서비스를 시작하기 때문에 원하는대로 서비스를 조정할 수 있습니다.
  4. 강력한 서비스 제어 도구 : 대부분의 신호를 서비스에 보낼 수 있으며 서비스를 안정적으로 위아래로 가져올 수 있습니다.
  5. 귀하의 서비스는 깨끗한 실행 환경을 보장 init합니다. 제공 하는 것과 동일한 환경, 프로세스 제한 등으로 실행됩니다 .

단점 :

  1. 각 서비스에는 약간의 설정이 필요합니다. 고맙게도 이것은 서비스 당 한 번만 수행하면됩니다.
  2. 서비스는 포 그라운드에서 실행되도록 설정되어야합니다. 또한 최상의 결과를 얻으려면 syslog 또는 기타 파일이 아닌 표준 출력 / 표준 오류에 기록하도록 설정해야합니다.
  3. daemontools 방식을 처음 사용하는 경우 학습 곡선이 가파 릅니다. 을 사용하여 서비스를 다시 시작해야 svc하며 실행 스크립트를 직접 실행할 수 없습니다 (그러면 관리자의 제어를받지 않기 때문입니다).
  4. 많은 하우스 키핑 파일과 많은 하우스 키핑 프로세스. 각 서비스에는 자체 서비스 디렉토리가 필요하며 각 서비스는 하나의 감독자 프로세스를 사용하여 서비스가 종료되면 자동으로 다시 시작합니다. (당신이 많은 서비스가있는 경우, 당신은 볼 을 많이supervise프로세스 테이블에서 프로세스를.)

균형 적으로 daemontools는 귀하의 요구에 맞는 훌륭한 시스템이라고 생각합니다. 설정 및 유지 관리 방법에 대한 질문을 환영합니다.


답변

나는 당신이 시도하고 싶을 것이라고 생각합니다 start-stop-daemon(8). /etc/init.dLinux 배포판의 스크립트에서 예제를 확인하십시오 . 호출 된 명령 줄 또는 PID 파일로 시작된 프로세스를 찾을 수 있으므로 스크립트에 대한 감시자가되는 것을 제외하고 모든 요구 사항과 일치합니다. 그러나 필요한 경우 스크립트를 다시 시작하는 다른 데몬 감시 스크립트를 언제든지 시작할 수 있습니다.


답변

daemonize 살펴 봐야 합니다. 두 번째 복사본을 감지 할 수 있습니다 (하지만 파일 잠금 메커니즘을 사용함). 또한 다른 UNIX 및 Linux 배포판에서도 작동합니다.

자동으로 애플리케이션을 데몬으로 시작해야하는 경우 적절한 초기화 스크립트를 만들어야합니다.

다음 템플릿을 사용할 수 있습니다.

#!/bin/sh
#
# mydaemon     This shell script takes care of starting and stopping
#               the <mydaemon>
#

# Source function library
. /etc/rc.d/init.d/functions


# Do preliminary checks here, if any
#### START of preliminary checks #########


##### END of preliminary checks #######


# Handle manual control parameters like start, stop, status, restart, etc.

case "$1" in
  start)
    # Start daemons.

    echo -n $"Starting <mydaemon> daemon: "
    echo
    daemon <mydaemon>
    echo
    ;;

  stop)
    # Stop daemons.
    echo -n $"Shutting down <mydaemon>: "
    killproc <mydaemon>
    echo

    # Do clean-up works here like removing pid files from /var/run, etc.
    ;;
  status)
    status <mydaemon>

    ;;
  restart)
    $0 stop
    $0 start
    ;;

  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    exit 1
esac

exit 0


답변

이미 언급 한 daemonize및에 대한 대안으로 libslack 패키지 daemontools데몬 명령이 있습니다.

daemon 매우 구성 가능하며 자동 재시작, 로깅 또는 pidfile 처리와 같은 모든 지루한 데몬 작업을 처리합니다.


답변

특별히 OS X를 사용하고 있다면 launchd가 어떻게 작동하는지 살펴 보는 것이 좋습니다. 스크립트가 실행 중인지 자동으로 확인하고 필요한 경우 다시 시작합니다. 또한 모든 종류의 스케줄링 기능 등을 포함합니다. 요구 사항 1과 2를 모두 충족해야합니다.

스크립트 사본 하나만 실행할 수 있도록하려면 PID 파일을 사용해야합니다. 일반적으로 현재 실행중인 인스턴스의 PID를 포함하는 파일을 /var/run/.pid에 씁니다. 프로그램이 실행될 때 파일이 존재하면 파일의 PID가 실제로 실행 중인지 확인합니다 (프로그램이 충돌했거나 PID 파일을 삭제하는 것을 잊었을 수 있음). 그렇다면 중단하십시오. 그렇지 않은 경우 실행을 시작하고 PID 파일을 덮어 씁니다.


답변

Daemontools ( http://cr.yp.to/daemontools.html )는 dj bernstein이 작성한이 작업을 수행하는 데 사용되는 꽤 하드 코어 유틸리티 세트입니다. 나는 이것을 약간의 성공으로 사용했습니다. 그것에 대한 성가신 부분은 스크립트를 실행할 때 보이는 결과를 반환하지 않는다는 것입니다. 단지 보이지 않는 반환 코드 일뿐입니다. 그러나 일단 실행되면 방탄입니다.