[shell] nohup에서 이미 실행중인 프로세스를 어떻게 배치합니까?
이미 오랫동안 실행중인 프로세스가 있으며 종료하고 싶지 않습니다.
nohup 아래에 어떻게 배치합니까 (즉, 터미널을 닫아도 계속 실행되게하려면 어떻게해야합니까?)
답변
bash 의 작업 제어 를 사용하여 프로세스를 백그라운드로 보내기 :
- Ctrl+ Z프로그램을 중지 (일시 중지)하고 쉘로 돌아갑니다.
bg
백그라운드에서 실행합니다.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하게합니다.
답변
위의 좋은 답변입니다. 설명을 추가하고 싶었습니다.
당신은 disown
pid 나 프로세스, 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 errno
gdb 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
, 그것은 나를 위해 일하지 않았다
그런 다음 다음 명령을 시도하고 매우 잘 작동했습니다.
-
SOMECOMMAND를 실행하십시오 (예 🙂
/usr/bin/python /vol/scripts/python_scripts/retention_all_properties.py 1
. -
Ctrl+ Z프로그램을 중지 (일시 중지)하고 쉘로 돌아갑니다.
-
bg
백그라운드에서 실행합니다. -
disown -h
터미널이 닫힐 때 프로세스가 종료되지 않습니다. -
exit
셸에서 빠져 나오려면 입력하십시오. 이제는 자체 프로세스에서 백그라운드에서 작업이 실행되므로 셸에 묶이지 않기 때문에 작업을 진행하는 것이 좋습니다.
이 프로세스는 running과 동일합니다 nohup SOMECOMMAND
.