작업 및 프로세스 ID를 인쇄하지 않고 백그라운드에서 bash 명령 실행


83

bash에서 백그라운드에서 프로세스를 실행하는 것은 매우 쉽습니다.

$ echo "Hello I'm a background task" &
[1] 2076
Hello I'm a background task
[1]+  Done                    echo "Hello I'm a background task"

그러나 출력은 장황합니다. 첫 번째 줄에는 백그라운드 작업의 작업 ID와 프로세스 ID가 인쇄되고 명령의 출력이 표시되고 마지막으로 작업 ID, 작업 상태 및 작업을 트리거 한 명령이 표시됩니다.

마지막에 앰퍼샌드없이 출력이 정확히 표시되도록 백그라운드 작업 실행의 출력을 억제하는 방법이 있습니까? 즉 :

$ echo "Hello I'm a background task" &
Hello I'm a background task

내가 묻는 이유는 탭 완성 명령의 일부로 백그라운드 프로세스를 실행하여 해당 명령의 출력이 의미를 갖도록 중단되지 않아야하기 때문입니다.


bash-completion 스크립트에서 수행하는 모든 작업에 2> / dev / null을 추가해야한다고 가정합니다
sehe

답변:


98

완료와는 관련이 없지만 하위 쉘에 호출을 넣어 출력을 억제 할 수 있습니다.

(echo "Hello I'm a background task" &)

3
감사합니다. 확실히 작동합니다. 불행히도 bash-completion 함수에서 이와 같은 스크립트를 실행할 때 bash는 완료 결과를 제공하기 전에 하위 프로세스가 완료 될 때까지 기다리는 것처럼 보입니다. 이것은 bash-completion에 의해 백그라운드 워커를 트리거하는 것이 가능하지 않은 것처럼 보이기 때문에 불행한 일입니다.
Alex Spurling

13
wait백그라운드 작업을 완료 하려면 이것을 사용할 수 없습니다 .
arekolek

13

@shellter의 답변을 바탕으로 이것은 나를 위해 일했습니다.

tyler@Tyler-Linux:~$ { echo "Hello I'm a background task" & disown; } 2>/dev/null; sleep .1;
Hello I'm a background task
tyler@Tyler-Linux:~$

나는 그 이유를 모르지만 bash가 프로세스 ID를 출력하는 것을 방지하는 오래된 게시물에서 기억했습니다.


@Tyzoid. 나는 bash 셸 (v 4.2.37)에서 솔루션을 시도했으며 흥미로운 결과를 얻었습니다. 1. ;끝에 추가하는 것만으로도 같은 결과를 얻었습니다 . (수면없이). 2.하지만 내가 echo STDERR 2>&1"다음"줄에 추가했을 때 그게 [1]+ Done ...나타났습니다! . (지금 언급 한대로) 3. 내 솔루션은 작동 ksh하고 echo STDERR 2>&1만 출력 STDERR을 생성합니다. 글쎄, 우리 모두를 위해 살고 배우십시오. 모두에게 행운을 빕니다.
셸터

12

일부 최신 버전의 bash 및 ksh93에서는 하위 쉘 또는 프로세스 그룹 (예 :)으로 묶을 수 있습니다 { ... }.

/home/shellter $ { echo "Hello I'm a background task" & } 2>/dev/null
Hello I'm a background task
/home/shellter $

5
중괄호를 사용하면 출력의 마지막 줄이 계속 표시됩니다 (왜 보이지 않는지 모르겠습니다).
Alex Spurling

나는 이것을 정확하게 복사했지만 나를 위해 작동하지 않지만 @AlexSpurling이 말한 것처럼 여전히 출력을 보여줍니다. 다른 사람들이 그것을 찬성했기 때문에 내가 뭔가 잘못하고 있을지도 모르지만, 나는 그것을 -1로 줘야 할 것 같습니다.
Mark

1
@Mark : 방금 이것으로 몇 가지 빠른 테스트를 수행했으며 문제는 계속해서 ksh93+기본 셸로 사용한다는 것 입니다. 이 코드는 ksh에서 약속 한대로 작동합니다. 그러나 OP에 태그가 붙어 있으므로 bash귀하의 dv를 이해합니다. @Tyzoid의 답변에서 bash 테스트 결과를 참조하십시오. 모두에게 행운을 빕니다!
셸터

이것이 bash에서 작동하지 않는다는 것을 분명히 했으므로 -1을 제거하겠습니다.
Mark

1
나에게 이것은 Bash 기능에서 훌륭하게 작동 wait $!하며, 수락 된 답변의 경우가 아닌 것처럼 보이는 프로세스도 기다릴 수 있습니다 .
Jonatan Öström


6

이 답변을 바탕으로 더 간결하고 정확한 것을 생각해 냈습니다.

silent_background() {
    { 2>&3 "$@"& } 3>&2 2>/dev/null
    disown &>/dev/null  # Prevent whine if job has already completed
}
silent_background date

완전한! 다른
용도로

5

시험:

user@host:~$ read < <( echo "Hello I'm a background task" & echo $! )
user@host:~$ echo $REPLY
28677

그리고 출력PID를 모두 숨겼습니다 . $ REPLY에서 여전히 PID 를 검색 할 수 있습니다.


1
이것은 완벽 해요! 감사합니다
Adham Atta

4

이전 게시물에 대한 답변에 대해 죄송하지만 다른 사람에게 유용하다고 생각하며 Google의 첫 번째 답변입니다.

이 방법 (서브 쉘)에 문제가 있고 '대기'를 사용하고있었습니다. 그러나 함수 내에서 실행하면서 다음과 같이 할 수있었습니다.

function a {
    echo "I'm background task $1"
    sleep 5
}

function b {
    for i in {1..10}; do
        a $i &
    done
    wait
} 2>/dev/null

그리고 내가 그것을 실행할 때 :

$ b
I'm background task 1
I'm background task 3
I'm background task 2
I'm background task 4
I'm background task 6
I'm background task 7
I'm background task 5
I'm background task 9
I'm background task 8
I'm background task 10

프롬프트를 다시 받기까지 5 초의 지연이 있습니다.


1

서브 쉘 솔루션도 작동하지만 백그라운드 작업을 기다릴 수 있기를 원했습니다 (끝에 "완료"메시지가 표시되지 않음). $!현재 대화식 쉘에서 서브 쉘에서 "대기 가능"하지 않습니다. 나를 위해 일한 유일한 해결책은 매우 간단한 자체 대기 기능을 사용하는 것입니다.

myWait() {
  while true; do
    sleep 1; STOP=1
    for p in $*; do
      ps -p $p >/dev/null && STOP=0 && break
    done
    ((STOP==1)) && return 0
  done
}

i=0
((i++)); p[$i]=$(do_whatever1 & echo $!)
((i++)); p[$i]=$(do_whatever2 & echo $!)
..
myWait ${p[*]}

충분히 쉽습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.