[shell] nohup에서 이미 실행중인 프로세스를 어떻게 배치합니까?

이미 오랫동안 실행중인 프로세스가 있으며 종료하고 싶지 않습니다.

nohup 아래에 어떻게 배치합니까 (즉, 터미널을 닫아도 계속 실행되게하려면 어떻게해야합니까?)



답변

bash 의 작업 제어 를 사용하여 프로세스를 백그라운드로 보내기 :

  1. Ctrl+ Z프로그램을 중지 (일시 중지)하고 쉘로 돌아갑니다.
  2. bg 백그라운드에서 실행합니다.
  3. disown -h [job-spec]여기서 [job-spec]은 작업 번호 ( %1첫 번째 실행 작업의 경우와 같이 jobs명령으로 번호를 찾습니다 )이므로 터미널을 닫을 때 작업이 종료되지 않습니다.

답변

어떤 이유로 Ctrl+ Z도 작동하지 않는다고 가정 하고 다른 터미널로 이동하여 프로세스 ID를 찾고 (을 사용하여 ps) 다음을 실행하십시오.

kill -SIGSTOP PID
kill -SIGCONT PID

SIGSTOP프로세스를 일시 중단하고 SIGCONT백그라운드에서 프로세스를 다시 시작합니다. 이제 두 터미널을 모두 닫아도 프로세스가 중단되지 않습니다.


답변

쉘에서 실행중인 작업을 분리하는 명령 (=는 nohup)은 disown기본 쉘 명령입니다.

bash-manpage (man bash)에서 :

폐기 [-ar] [-h] [jobspec …]

옵션이 없으면 각 작업 스펙이 활성 작업 테이블에서 제거됩니다. -h 옵션이 제공되면 각 jobspec은 테이블에서 제거되지 않지만 쉘이 SIGHUP을 수신 할 때 SIGHUP이 작업으로 전송되지 않도록 표시됩니다. jobspec이없고 -a 또는 -r 옵션이 제공되지 않으면 현재 작업이 사용됩니다. jobspec이 제공되지 않으면 -a 옵션은 모든 작업을 제거하거나 표시하는 것을 의미합니다. jobspec 인수가없는 -r 옵션은 작업을 실행중인 작업으로 제한합니다. jobspec이 유효한 작업을 지정하지 않으면 리턴 값은 0입니다.

즉, 간단한

disown -a

작업 테이블에서 모든 작업을 제거하고 nohup하게합니다.


답변

위의 좋은 답변입니다. 설명을 추가하고 싶었습니다.

당신은 disownpid 나 프로세스, disown직업 이 될 수 없으며 그것은 중요한 차이점입니다.

작업은 쉘에 첨부 된 프로세스의 개념 인 작업이므로 작업을 백그라운드로 던지고 (일시 중단하지 말고) 제거해야합니다.

발행물:

%  jobs
[1]  running java
[2]  suspended vi
%  disown %1

Unix Job Control에 대한 자세한 내용은 http://www.quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/jobcontrol/ 을 참조 하십시오 .


답변

불행히도 disown배쉬에만 적용되며 모든 쉘에서 사용 가능한 것은 아닙니다.

Unix의 특정 특징 (예 : AIX 및 Solaris)은 nohup실행중인 프로세스에 적용 할 수있는 명령 자체 에 대한 옵션 이 있습니다.

nohup -p pid

http://en.wikipedia.org/wiki/Nohup 참조


답변

노드의 대답은 정말 훌륭하지만 stdout 및 stderr를 리디렉션하는 방법에 대한 의문을 남겼습니다. 유닉스 및 리눅스 에서 해결책을 찾았 지만 완벽하지 않습니다. 이 두 가지 솔루션을 병합하고 싶습니다. 여기있어:

내 테스트를 위해 loop.sh라는 작은 bash 스크립트를 만들었습니다.

$./loop.sh

이제이 프로세스의 PID를 어떻게 든 얻으십시오. 일반적으로 ps -C loop.sh충분하지만 제 경우에는 인쇄됩니다.

이제 다른 터미널로 전환 할 수 있습니다 (또는 동일한 터미널에서 ^ Z를 누름). 이제이 gdb프로세스에 첨부해야합니다.

$ gdb -p <PID>

스크립트가 중지됩니다 (실행중인 경우). 그 상태를 확인할 수있다 ps -f <PID>여기서 STAT필드는 ‘+ T'(또는 ^ Z ‘T’의 경우), 어떤 수단 (남자 PS (1))

    T Stopped, either by a job control signal or because it is being traced
    + is in the foreground process group

(gdb) call close(1)
$1 = 0

Close (1)은 성공하면 0을 반환합니다.

(gdb) call open("loop.out", 01102, 0600)
$6 = 1

성공하면 Open (1)은 새 파일 설명자를 반환합니다.

이 개방은와 같습니다 open(path, O_TRUNC|O_CREAT|O_RDWR, S_IRUSR|S_IWUSR). 대신 O_RDWR O_WRONLY적용될 수 있지만 /usr/sbin/lsof모든 std * 파일 처리기 ( FD열)에 대해 ‘u’라고 표시됩니다 O_RDWR.

/usr/include/bits/fcntl.h 헤더 파일의 값을 확인했습니다.

출력 파일은 O_APPEND,로 열 수 nohup있지만 man open(2)NFS 문제 일 수 있으므로이 제안되지 않습니다 .

반환 값으로 -1을 얻는다면 call perror("")에러 메시지 를 출력합니다. errno가 필요하면 p errnogdb comand를 사용하십시오 .

이제 새로 리디렉션 된 파일을 확인할 수 있습니다. /usr/sbin/lsof -p <PID>인쇄물:

loop.sh <PID> truey    1u   REG   0,26        0 15008411 /home/truey/loop.out

원하는 경우 다른 파일 이름 을 사용 call close(2)하고 call open(...)다시 사용 하려면 stderr을 다른 파일로 리디렉션 할 수 있습니다 .

이제 첨부 파일 bash이 해제되고 종료 할 수 있습니다 gdb.

(gdb) detach
Detaching from program: /bin/bash, process <PID>
(gdb) q

스크립트가 gdb다른 터미널에서 중지 된 경우 계속 실행됩니다. loop.sh의 터미널로 다시 전환 할 수 있습니다. 이제 화면에 아무것도 쓰지 않지만 파일을 실행하고 쓰고 있습니다. 우리는 그것을 배경에 넣어야합니다. 따라서를 누릅니다 ^Z.

^Z
[1]+  Stopped                 ./loop.sh

(이제 ^Z처음에 눌린 것과 같은 상태 입니다.)

이제 작업 상태를 확인할 수 있습니다.

$ ps -f 24522
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh
$ jobs
[1]+  Stopped                 ./loop.sh

따라서 프로세스는 백그라운드에서 실행되고 터미널에서 분리되어야합니다. jobs대괄호 안에 있는 명령 출력 의 숫자는 내부 작업을 식별합니다 bash. bash작업 번호 앞에 ‘%’기호를 적용하는 다음 내장 명령 에서 사용할 수 있습니다 .

$ bg %1
[1]+ ./loop.sh &
$ disown -h %1
$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID><PPID>  0 11:16 pts/36   S      0:00 /bin/bash ./loop.sh

이제 우리는 호출하는 bash에서 종료 할 수 있습니다. 프로세스는 백그라운드에서 계속 실행됩니다. PPID를 종료하면 1 (init (1) 프로세스)이되고 제어 터미널을 알 수 없게됩니다.

$ ps -f <PID>
UID        PID  PPID  C STIME TTY      STAT   TIME CMD
<UID>    <PID>     1  0 11:16 ?        S      0:00 /bin/bash ./loop.sh
$ /usr/bin/lsof -p <PID>
...
loop.sh <PID> truey    0u   CHR 136,36                38 /dev/pts/36 (deleted)
loop.sh <PID> truey    1u   REG   0,26     1127 15008411 /home/truey/loop.out
loop.sh <PID> truey    2u   CHR 136,36                38 /dev/pts/36 (deleted)

논평

명령을 포함하는 파일 (예 : loop.gdb)을 만들어 gdb를 자동화하고 실행할 수 gdb -q -x loop.gdb -p <PID>있습니다. 내 loop.gdb는 다음과 같습니다.

call close(1)
call open("loop.out", 01102, 0600)
# call close(2)
# call open("loop.err", 01102, 0600)
detach
quit

또는 대신 하나의 라이너를 사용할 수 있습니다.

gdb -q -ex 'call close(1)' -ex 'call open("loop.out", 01102, 0600)' -ex detach -ex quit -p <PID>

이것이 솔루션에 대한 완전한 설명이기를 바랍니다.


답변

nohup으로 실행중인 프로세스를 보내려면 ( http://en.wikipedia.org/wiki/Nohup )

nohup -p pid , 그것은 나를 위해 일하지 않았다

그런 다음 다음 명령을 시도하고 매우 잘 작동했습니다.

  1. SOMECOMMAND를 실행하십시오 (예 🙂 /usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1.

  2. Ctrl+ Z프로그램을 중지 (일시 중지)하고 쉘로 돌아갑니다.

  3. bg 백그라운드에서 실행합니다.

  4. disown -h 터미널이 닫힐 때 프로세스가 종료되지 않습니다.

  5. exit셸에서 빠져 나오려면 입력하십시오. 이제는 자체 프로세스에서 백그라운드에서 작업이 실행되므로 셸에 묶이지 않기 때문에 작업을 진행하는 것이 좋습니다.

이 프로세스는 running과 동일합니다 nohup SOMECOMMAND.