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


940

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

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


29
같은 문제에 직면 한 사람에게 : 입력 yourExecutable &하고 출력이 화면에 계속 Ctrl+C나타나고 아무것도 멈추지 않는 것처럼 보이지만 화면이 출력으로 스크롤 되어도 맹목적으로 입력 disown;하고 누르십시오. Enter입력 중입니다. 프로세스가 폐기되고 프로세스가 종료되지 않고 터미널을 닫을 수 있습니다.
Nav

답변:


1367

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

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

38
문제는 "nohup 아래에 넣는"방법 disown -h이었을 것입니다. 아마도 가장 정확한 대답은 다음과 같습니다. "disown이 nohup과 비슷하게 동작하도록하십시오 (즉, 작업은 쉘을 종료 할 때까지 현재 쉘의 프로세스 트리에 남아 있습니다). 이 쉘이 시작한 모든 작업 " ([ quantprinciple.com/invest/index.php/docs/tipsandtricks/unix/… )
Jan-Philip Gehrcke 박사

8
나중에 작업을 어떻게 복구합니까? ps -e를 사용하여 실행되는 것을 볼 수 있습니다.
Paulo Casaretto

26
disowndisown이 프로세스를 데몬으로 만든 후 작업의 출력을 볼 수 없습니다. 즉 표준 입력 / 출력이 / dev / null로 리디렉션됩니다. 따라서 작업을 my_job_command | tee my_job.log
취소하려는

8
어떻게 든 'my_job_command | 명령이 이미 실행 된 tee my_job.log ' ?
arod

23
disown프로세스에서 파이프를 분리합니다. 파이프를 다시 부착하려면 이 스레드에gdb 설명 된대로 사용하십시오 . 더 구체적으로, 이 게시물 입니다.
mbrownnyc

185

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

kill -SIGSTOP PID 
kill -SIGCONT PID

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


10
예, OS 문제입니다. Windows의 Cygwin에서는 kill이 작동하지 않습니다.
Pungs

6
작업이 다른 ssh 세션에서 시작된 경우에도 매우 유용합니다.
Amir Ali Akbari

5
disown %1터미널을 닫기 전에 첫 번째 터미널에서 수행해야 합니다.
프레드

1
이것은 콘솔로 그래픽 인터페이스를 시작했기 때문에 유용합니다 (제 경우 kwin에는 결과를 생각하지 않고 충돌 후 곤솔에서 시작했습니다 ). 그래서 kwin을 멈 추면 모든 것이 멈췄을 것이고 도망 칠 가능성도 없었습니다 bg!
Michele

@fred 나는 이것을하지 않았으며 계속 실행되는 것처럼 보였다. 가능하거나 잘못된 PID를 쳤습니까?
아무도

91

쉘에서 실행중인 작업을 분리하는 명령 (=는 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하게합니다.


9
disown -a모든 작업을 제거합니다. 단순 disown은 현재 작업 만 제거합니다. 답변의 맨 페이지가 말합니다.
Rune Schjellerup Philosof

73

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

당신은 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/ 을 참조 하십시오 .


48

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

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

nohup -p pid

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


AIX및 에만 해당됩니다 Solaris. "nohup의 AIX 및 Solaris 버전에는 향후 SIGHUP 신호를 무시하도록 실행중인 프로세스를 수정하는 -p 옵션이 있습니다. 위에서 설명한 bash 내장 거부와 달리 nohup -p는 프로세스 ID를 승인합니다." 출처
AlikElzin-kilaka

27

노드의 대답은 정말 훌륭하지만 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>

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


실제로 매우 유익하며 간단한 경우에는 잘 작동합니다. 그러나 더 복잡한 경우는 비참하게 실패 할 수 있습니다. 나는 오늘 그 중 하나를 가지고 있었다 : 내 프로세스는 출력을 수행하는 다른 프로세스 (아마도 stderr)를 생성했지만 마스터와의 통신을 위해 stdout을 연결했다. 자식이 stderr를 상속했기 때문에 마스터 FD 리디렉션은 효과가 없었으며 자식 stdout을 닫으면 파이프의 다른 쪽 끝에서 대기중인 마스터가 실패했습니다. X- | 시도하기 전에 프로세스를 잘 알고 있어야합니다.
cmaster-monica reinstate

@cmaster 핸들이 lsof(파일 핸들의 이름이 pipe아닌 /dev/pts/1)을 사용하거나 ls -l /proc/<PID>/fd/<fd>(이것이 핸들의 심볼릭 링크를 표시 함 )을 사용하여 리디렉션되는지 확인할 수 있습니다 . 또한 서브 프로세스는 여전히 출력을 경로 재 지정할 수 없으므로 파일로 경로 재지 정해야합니다.
TrueY

7

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.


3

내 AIX 시스템에서 시도했습니다

nohup -p  processid>

이것은 잘 작동했습니다. 터미널 창을 닫은 후에도 프로세스를 계속 실행했습니다. 기본 쉘로 ksh가 있으므로 bgand disown명령이 작동하지 않았습니다.


2
  1. ctrl+ z -작업을 일시 중지합니다 (취소하지 않음).
  2. bg -이것은 작업을 백그라운드로 놓고 실행중인 프로세스로 돌아갑니다.
  3. disown -a -이것은 작업과 함께 모든 첨부 파일을 잘라냅니다 (따라서 터미널을 닫을 수 있으며 여전히 실행됩니다)

이 간단한 단계를 통해 프로세스를 계속 실행하면서 터미널을 닫을 수 있습니다.

그것은에 넣어 실 거예요 nohup(귀하의 질문에 대한 이해를 기반으로, 당신은 여기 필요하지 않습니다).


disown -a의 동작은 모든 작업에서 첨부 파일을 잘라내는 것이라고 생각합니다. 그러나 stdin / stdout 파이프 라인을 종료하지 않습니다. 즉, 프로세스는 터미널에서 쓰기 / 읽기를 시도합니다.
Kelthar

-2

이것은 tcshell에있는 동안 Ubuntu Linux에서 나를 위해 일했습니다.

  1. CtrlZ 일시 정지

  2. bg 백그라운드에서 실행

  3. jobs 직업 번호를 얻기 위해

  4. nohup %n 여기서 n은 작업 번호입니다.


2
아니, 그것은 작동하지 않습니다 :nohup: failed to run command '%1': No such file or directory
Dunatotatos
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.