대기열에서와 같이 명령을 실행하는 방법


42

다양한 파일을 다양한 폴더로 복사해야합니다. 모든 복사 명령을 bash 스크립트에 추가 한 다음 실행할 수 있지만 해당 복사 "큐"에 명령을 추가하려면 완료 될 때까지 기다려야합니다.

대기열로 명령을 실행하고 작업이 실행되는 동안 해당 대기열에 명령을 추가하는 방법이 있습니까?

다른 방식으로 설명하면서 장기 실행 작업을 시작하고 싶습니다. 그것이 실행되는 동안 나는 첫 번째 것이 끝날 때까지 실제로 시작하지 않는 다른 것을 시작하고 싶습니다. 그런 다음 마지막 항목 뒤에 다른 항목을 추가하십시오. 어떻게 든 가능합니까?


3
문제를 해결하는 답변을 받아들이는 것이 좋습니다. 당신을 위해 일할 몇 가지가있는 것 같습니다.
holmb

2
그렇습니다, 나는 원했습니다. 문제는 Mac을 사용하는 회사에서 일할 때 이것을 물었다는 것입니다. 나는 더 이상 그곳에서 일하고 있지 않으며, 나 자신도 Mac을 가지고 있지 않으므로이 중 어떤 것도 테스트 할 방법이 없다. 실제로 작동하는지 테스트 할 수 없을 때 하나를 답변으로 표시하는 데 불편 함을 느끼지 않으므로 지금은 사람들이 해당 답변에 투표하여 "답변"이 그런 식으로 나타날 수 있기를 바랍니다. 대신에.
Svish

답변:


25

at지정된 시간에 명령을 실행하는 것으로 가장 잘 알려진 이 유틸리티에는 대기열 기능도 있으며 명령 실행을 시작하도록 요청할 수 있습니다. 표준 입력에서 실행할 명령을 읽습니다.

echo 'command1 --option arg1 arg2' | at -q myqueue now
echo 'command2 ...' | at -q myqueue now

batch명령은 동일합니다 at -q b -m now( -m크론가하는 원하는 경우에, 당신에게 발송됩니다, 명령 출력을 의미). 모든 유닉스 변형이 큐 이름 ( -q myqueue)을 지원하는 것은 아닙니다 . 라는 단일 대기열로 제한 될 수 있습니다 b. Linux at는 단일 문자 대기열 이름으로 제한됩니다.


2
리눅스에서는 적어도 이전 명령이 끝날 때까지 기다리지 않는 것 같습니다.
wds

@wds 데비안 wheezy에서 작동합니다. 어디서 어떻게 깨졌습니까? 명령이 완료 될 때까지만 기다리십시오. 명령이 부모보다 오래 지속되는 하위 프로세스를 시작하면 at은 하위 프로세스를 기다리지 않습니다.
Gilles 'SO- 악마 그만두 다'

CentOS 6을 사용해 보았습니다. 간단한 "sleep x"로 테스트했습니다. 나는 그것을 실행하기 위해 무엇을 해야할지 모르겠지만 서브 쉘을 시작하고 그 서브 쉘이 결과를 기다려야한다고 가정합니다 (수면 호출은 즉시 반환되지 않습니다).
wds

대기열 이름뿐만 아니라 '지금'도 표준으로 표시되지 않습니다. 우분투의 bash가 그것에 대해 불평하고 있습니다 ...
winwaed

오 @winwaed, 그것의 now, 아니 -t now, 죄송합니다. 샘플 코드에서 잘못되었다는 것을 알지 못했습니다.
질 'SO-정지 존재 악마'

23

&명령의 끝에 추가 하여 명령을 백그라운드로 보낸 후 다음 명령을 wait실행하기 전에 명령으로 보냅니다 . 예를 들면 다음과 같습니다.

$ command1 &
$ wait; command2 &
$ wait; command3 &
$ ...

2
예! 이 구문은 무언가를 시작한 다음 무언가를 대기열에 넣을 수있는 방법을 찾기 위해 stackoverflow를
살펴볼 때 훌륭

2
그 동안 해당 명령 중 하나라도 마음이 바뀌면 wait? 내 모든 살인 사건에는 영향을 미치지 않는 것 같습니다.
Ken Williams

1
당신은 명령을 죽입니다. 은 wait이전 사람이 마칠 때까지 단순히 작업을 중지합니다.
Gert Sønderby

이 작동 nohup합니까?
Michael

11

Brad와 Mankoff의 솔루션은 모두 좋은 제안입니다. 두 가지의 조합과 비슷한 또 다른 것은 GNU Screen 을 사용 하여 대기열을 구현하는 것입니다. 백그라운드에서 실행할 수 있다는 장점이 있으며, 언제든지 확인할 수 있으며, 새 명령을 대기열에 추가하면 이전 명령이 종료 된 후에 실행될 명령을 버퍼에 붙여 넣기 만하면됩니다.

먼저 다음을 실행하십시오.

$ screen -d -m -S queue

(우연히, 이제 멋진. screenrc 파일 을 가지고 놀기에 좋은 시간입니다 )

그러면 대기열이라는 배경 화면 세션이 나타납니다.

이제 원하는만큼 명령을 대기열에 넣습니다.

screen -S queue -X stuff "echo first; sleep 4; echo second^M"

테스트를 위해 위의 여러 명령을 수행하고 있습니다. 사용 사례는 다음과 같습니다.

screen -S queue -X stuff "echo first^M"
screen -S queue -X stuff "echo second^M"

위의 줄에서 "^ M"은 포함 된 줄 바꿈을 가져 오는 방법으로, 나중에 스크린이 기존 bash 쉘에 채워진 후에 해석 될 것입니다. 해당 시퀀스를 얻으려면 "CTL-V"를 사용하십시오.

간단한 셸 스크립트를 만들어서 자동화하고 명령을 대기시키는 것은 매우 쉽습니다. 그런 다음 백그라운드 큐의 상태를 확인할 때마다 다음을 통해 다시 연결하십시오.

screen -S queue -r

기술적으로는 화면 세션의 이름을 지정할 필요조차 없으며 정상적으로 작동하지만 일단 연결되면 항상 실행중인 상태로두기를 원할 것입니다. ;-)

물론 그렇게하면, 또 다른 좋은 방법은 현재 창 중 하나의 이름을 "큐"로 지정하고 사용하는 것입니다.

screen -S queue -p queue -X stuff "command"

기본적으로 실행중인 화면 세션에서 명령을 "입력"하는 것처럼 보이기 때문에 첫 번째 명령이 완료된 후 쉘이 다시 제어 할 때이 명령이 시작됩니다. 즉, @mankoff의 솔루션과 동일하지만 더 멋진 도구를 사용하여 입력을 수행합니다.
Ken Williams

대부분의 차이점은 스크린 솔루션이 더 나은 자동화를 지원한다는 것입니다. 간단한 인터페이스를 사용하여 손으로 직접 작업하거나 스크립트로 다른 작업을 수행 할 수 있습니다.
Jordan

@ 조던 아주 좋아요, 그것은 나를 위해 작동합니다. 그러나 -X 이후의 "stuff"는 무엇입니까?
콘스탄틴

@Konstantin gnu.org/software/screen/manual/html_node/Paste.html#Paste (TL; DR-입력 한 것처럼 터미널에 나오는 내용)
Jordan

@ 조던 아, 지금 봅니다. 명령입니다. 나는 그것이 임의의 문자열이라고 생각했습니다.
콘스탄틴

8

내가 설명하는 유스 케이스에 대해 큰 성공을 거둔 유틸리티가 있습니다. 최근에 기본 랩톱을 새로운 하드웨어로 옮겼는데, 일부 파일은 NAS로, 나머지는 새 컴퓨터로 옮겼습니다.

이것이 내가 한 방법입니다.

  1. 서로 연결될 수 있도록 네트워크 연결과 관련된 모든 시스템을 설정하십시오.

  2. 파일을 이동하는 시스템 (이하 소스 시스템)에서 rsync with apt-get install rsync및 비밀 소스 작업 스풀러 (웹 사이트 http://vicerveza.homeunix.net/~viric/soft/ts/ )를 설치하십시오. 데비안에서 패키지 이름 인 경우에 대한이 ts있다 task-spooler및 실행 파일로 이름이 변경됩니다 tsp과 피할 이름 충돌로 ts로부터 실행 moreutils패키지로 제공된다. 웹 사이트에서 링크 된 데비안 패키지는 Ubuntu와 함께 dpkg -i task-spooler_0.7.3-1_amd64.deb또는 이와 유사 하게 완벽하게 설치할 수 있습니다.

  3. 또한 모든 시스템에 SSH가 설치되어 있는지 확인하십시오 apt-get install openssh-server. 소스 머신에서 대상 머신에 비밀번호없이 로그인 할 수 있도록 SSH를 설정해야합니다. 가장 많이 사용하는 방법은 공개 키 인증 ssh-agent( https://www.google.se/search?q=ssh+public+key+authentication 참조 )이지만 때로는 더 쉬운 방법을 사용하기도합니다. 비밀번호 인증과 함께. SSH 클라이언트 구성에 다음을 추가하십시오 ( ~/.ssh/config또는 /etc/ssh/ssh_config).

    Host *
         ControlMaster auto
         ControlPath ~/.ssh/master-%r@%h:%p
    

    그런 다음 소스 시스템에서 터미널 하나를 열고로 로그인하여 ssh target1평소와 같이 인증 한 다음이 터미널을 열어 두십시오. 소켓 파일이라는 ~/.ssh/master-user@target1:22점에 유의하십시오.이 파일은 인증 된 마스터 세션을 열린 상태로 유지 user하고 연결에서 동일한 대상 호스트 이름과 포트를 사용하는 한 이후에 암호가없는 연결을 허용합니다 .

    이 시점에서 대상 시스템에 대한 인증을 요구하지 않고 로그인 할 수 있는지 확인해야합니다.

  4. 이제 ts rsync -ave ssh bigfile user@target1:단일 파일 또는 ts rsync -ave ssh bigdir user@target1:디렉토리에 대해 실행 하십시오 . rsync를 통해이 디렉토리 (에 후행 슬래시 포함하지 않는 것이 중요합니다 bigdir에 비해 bigdir/당신의 동등한 의미한다고 가정한다) 또는 rsync와 bigdir/*대부분의 다른 도구를.

    작업 스풀러가 프롬프트를 반환하고 이러한 많은 명령을 연속으로 대기열에 넣을 수 있습니다. ts인수없이 실행 큐를 검사하십시오 .

작업 스풀러에는 실행 대기열 재 배열, 다른 작업이 성공적으로 실행 된 경우에만 특정 작업 실행 등과 같은 많은 기능이 ts -h있습니다. 도움말을 참조하십시오 . 로 실행되는 동안 명령 출력을 검사하는 경우가 있습니다 ts -c.

이 작업을 수행하는 다른 방법이 있지만 사용 사례에는 모두 작업 스풀러가 포함됩니다. SMB를 통한 복사에는 없었던 파일 타임 스탬프를 보존하기 위해 SSH를 통한 rsync를 사용하기로 선택했습니다.


내가 알지 못했던 답변에 감사드립니다. ts매우 강력하고 사용하기 쉬운 것 같습니다 .github autotoolized 및 debianized에 있습니다.
Alex

@Alex 나는 당신의 포크를 보았고 원래 소스를 autotooling하고 debianize하는 것과 관련하여 무엇을했는지에 관심이 있었고 커밋을 보는 것은 원래 소스의 diff로 쉽게 사용할 수 없었습니다. 1 단계에서 원본 소스를 가져오고 2. 추가로 커밋하는 새 커밋을 강제로 푸시 하시겠습니까? 소스를 탐색하는 사람이 원본 소스에 대한 추가 사항을 (보다 쉽게) 신뢰할 수 있도록 도와줍니다. 이것은 PPA 또는 이와 유사한 패키지에서 설치하지 않는 몇 가지 패키지 중 하나이므로 포크로 직접 빌드하는 것이 좋습니다.
holmb

당신은 내가 안경을 바꿔야한다는 것을 알고 있습니다. 기존의 task-spooler:-) 에 대한 당신의 대답의 일부를 잃어 버렸습니다 .
Alex

점진적 커밋을 사용하여 저장소를 완료, 삭제 및 재 작성, 몇 가지 실수 (푸시 전에 더 많은 로컬 커밋을 대사해야 함)
Alex

4

나도 이와 같은 것들이 상당히 자주 필요합니다. after다른 프로세스가 끝날 때마다 명령을 실행 하는 작은 유틸리티를 작성했습니다 . 다음과 같이 보입니다 :

#!/usr/bin/perl

my $pid = shift;
die "Usage: $0 <pid> <command...>" unless $pid =~ /^\d+$/ && @ARGV;

print STDERR "Queueing process $$ after process $pid\n";
sleep 1 while -e "/proc/$pid";
exec @ARGV;

그런 다음 다음과 같이 실행하십시오.

% command1 arg1 arg2 ...  # creates pid=2853
% after 2853 command2 arg1 arg2 ... # creates pid=9564
% after 9564 command3 arg1 arg2 ...

다른 접근 방식에 비해이 방법의 가장 큰 장점은 첫 번째 작업을 특별한 방식으로 실행할 필요가 없으며 새 작업으로 모든 프로세스를 수행 할 수 있다는 것입니다.


멋진 스크립트 @ken. 때때로이 작업이 필요하므로 Task Spooler를 사용해 보는 것이 좋습니다. 내 대답을 참조하십시오.
holmb

깔끔하게 보입니다. 감사합니다. TS에서 누락 된 한 가지는 TS에서 시작되지 않은 작업을 수행하는 능력 인 것 같습니다. 기존 프로세스가 끝날 때까지 기다리는 새로운 TS 작업을 시작할 수 있다고 생각합니다.
Ken Williams

과연. 이것이 솔루션의 유용한 측면입니다.
holmb

2

Command1 && Command2

  • "&&"는 command1이 리턴 코드 0으로 완료된 후에 만 ​​command2가 실행됨을 의미합니다.
  • 참고 : a || 즉, command2가 0이 아닌 리턴 코드로 완료된 후에 만 ​​command2가 실행됨을 의미합니다.

1

이미 명령을 실행중인 쉘의 명령 행에 명령을 추가 할 수 있습니다.

주의해서 입력하거나 다른 곳에 입력하고 확인한 후 잘라서 붙여 넣기를 수행하십시오. 현재 명령이 출력 라인을 분출하고 있더라도 새로운 것을 입력하고 Enter 키를 누르면 모든 명령이 완료되거나 실행되기 전에 입력 될 때 실행됩니다.

예는 다음과 같습니다. 첫 번째를 실행하는 동안 (실제로 빠르게 입력하는 경우) 또는 두 번째가 실행되는 동안 전체를 잘라서 붙여 넣거나 후속 명령을 입력 할 수 있습니다.

echo "foo"
sleep 10; echo "bar"
sleep 3
echo "baz"

0

내가 생각할 수있는 가장 위험한 방법은 / tmp의 간단한 잠금 파일로 대기열 "상태"를 유지하는 것입니다. file1.sh가 cp 명령을 수행 할 때 / tmp에 잠금 파일 (또는 하드 링크)을 유지합니다. 완료되면 파일을 지우십시오. 다른 모든 스크립트는 / tmp에서 선택한 이름 지정 체계가있는 잠금 파일을 찾아야합니다. 당연히 이것은 모든 종류의 실패에 영향을 받지만 설정하는 것은 쉽지 않으며 bash 내에서 완전히 수행 할 수 있습니다.


어려움은 당신이 요구를 실행하려는 모든 작업이 잠금 파일을 유지하기 위해 수정 될 것을 요구하고, 요구가 알고 있기 때문에, 실제로 사용 (또는 매개 변수로 동의) 할 수 있는 사용에 파일을 잠급니다. 가능하면 대기열을 작업 외부에 두는 것이 가장 좋습니다.
Ken Williams
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.