다음 명령을 사용하여 crontab에서 매일 호출하는 작은 스크립트가 있습니다.
/homedir/MyScript &> some_log.log
이 방법의 문제점은 myScript가 완료된 후에 만 some_log.log가 생성된다는 것입니다. 프로그램이 실행되는 동안 프로그램의 출력을 파일로 플러시하여 다음과 같은 작업을 수행 할 수 있습니다.
tail -f some_log.log
진행 상황 등을 추적합니다.
다음 명령을 사용하여 crontab에서 매일 호출하는 작은 스크립트가 있습니다.
/homedir/MyScript &> some_log.log
이 방법의 문제점은 myScript가 완료된 후에 만 some_log.log가 생성된다는 것입니다. 프로그램이 실행되는 동안 프로그램의 출력을 파일로 플러시하여 다음과 같은 작업을 수행 할 수 있습니다.
tail -f some_log.log
진행 상황 등을 추적합니다.
sys.stdout.flush()
.
답변:
bash 자체는 실제로 로그 파일에 출력을 기록하지 않습니다. 대신 스크립트의 일부로 호출하는 명령은 각각 개별적으로 출력을 작성하고 원할 때마다 플러시합니다. 따라서 귀하의 질문은 실제로 bash 스크립트 내에서 명령을 강제로 플러시하는 방법이며, 그것은 그것이 무엇인지에 달려 있습니다.
stdbuf
있습니까? 이 의견 에 따르면 일부 배포판에서는 사용할 수없는 것 같습니다. 명확히 해 주시겠습니까?
stdbuf
GNU의로 coreutils의 일부입니다 문서는 gnu.org에서 찾을 수 있습니다
script -c <PROGRAM> -f OUTPUT.txt
키는 -f입니다. 맨 스크립트에서 인용 :
-f, --flush
Flush output after each write. This is nice for telecooperation: one person
does 'mkfifo foo; script -f foo', and another can supervise real-time what is
being done using 'cat foo'.
백그라운드에서 실행:
nohup script -c <PROGRAM> -f OUTPUT.txt
busybox
! (내 쉘은 이후 정지하지만, 무엇이든)
이것이 도움이 될까요?
tail -f access.log | stdbuf -oL cut -d ' ' -f1 | uniq
그러면 stdbuf 유틸리티를 사용하여 access.log의 고유 항목이 즉시 표시됩니다 .
stdbuf
우분투에서 사용할 수 있지만 어디서 구했는지 확실하지 않습니다.
stdbuf
일부입니다 . coreutilus
apt-file search /usr/bin/stdbuf
방법은 발견 여기에 문제가 당신이 당신의 스크립트에서 실행되는 프로그램이 자신의 작업을 완료 것을 기다릴 필요가 있다는 것입니다.
스크립트에서 백그라운드 에서 프로그램을 실행 하면 더 많은 것을 시도 할 수 있습니다.
일반적으로 전화 sync
종료하기 전에 파일 시스템 버퍼를 플러시 할 수 있으며 약간의 도움이 될 수 있습니다.
스크립트에서 일부 프로그램을 백그라운드 ( &
) 에서 시작하는 경우 스크립트를 종료하기 전에 완료 될 때까지 기다릴 수 있습니다 . 어떻게 작동하는지에 대한 아이디어를 얻으려면 아래에서 볼 수 있습니다.
#!/bin/bash
#... some stuffs ...
program_1 & # here you start a program 1 in background
PID_PROGRAM_1=${!} # here you remember its PID
#... some other stuffs ...
program_2 & # here you start a program 2 in background
wait ${!} # You wait it finish not really useful here
#... some other stuffs ...
daemon_1 & # We will not wait it will finish
program_3 & # here you start a program 1 in background
PID_PROGRAM_3=${!} # here you remember its PID
#... last other stuffs ...
sync
wait $PID_PROGRAM_1
wait $PID_PROGRAM_3 # program 2 is just ended
# ...
wait
작업과 PID
숫자 로 작동 하기 때문에 게으른 해결책은 스크립트 끝에 넣어야합니다.
for job in `jobs -p`
do
wait $job
done
더 어려운 것은 모든 자식 프로세스 의 끝을 검색하고 기다려야하기 때문에 백그라운드에서 다른 것을 실행하는 것을 실행하는 상황 입니다. 예를 들어 데몬 경우에는 그렇지 않을 수 있습니다. 완료되기를 기다리려면 :-).
노트 :
wait $ {!}는 마지막 백그라운드 프로세스 $!
의 PID 인 "마지막 백그라운드 프로세스가 완료 될 때까지 대기"를 의미 합니다. 따라서 wait ${!}
바로 뒤에 넣는 program_2 &
것은 직접 실행하는 것과 같습니다.program_2
것은 백그라운드로 보내지 않고&
의 도움에서 wait
:
Syntax
wait [n ...]
Key
n A process ID or a job specification
감사합니다 @user3258569
, 스크립트는 아마도 작동하는 유일한 것입니다 busybox
!
그래도 껍질이 얼어 붙었다. 원인을 찾아 보니 스크립트 매뉴얼 페이지 에서 "비대화 형 셸에서 사용하지 마십시오"라는 큰 빨간색 경고를 발견했습니다 .
script
주로 대화 형 터미널 세션 용으로 설계되었습니다. 표준 입력 (예 : 터미널이 아닌 경우echo foo | script
) 스크립트 세션 내에서 대화 형 쉘이 그리워하기 때문에, 다음 세션이 중단 될 수 있습니다 EOF를 하고script
때 세션을 종료하는 단서가 없습니다. 자세한 내용은 참고 섹션을 참조하십시오.
진실. script -c "make_hay" -f /dev/null | grep "needle"
나를 위해 껍데기를 얼리고 있었다.
경고에 반하여 echo "make_hay" | script
EOF를 통과 할 것이라고 생각 했기 때문에
echo "make_hay; exit" | script -f /dev/null | grep 'needle'
그리고 작동했습니다!
매뉴얼 페이지의 경고에 유의하십시오. 이것은 당신을 위해 작동하지 않을 수 있습니다.
stdbuf의 대안 awk '{print} END {fflush()}'
은 이것을 수행하기 위해 bash가 내장되어 있기를 바랍니다. 일반적으로 필요하지 않지만 이전 버전에서는 파일 설명자에 bash 동기화 버그가있을 수 있습니다.
작동할지 모르겠지만 전화는 sync
어떻습니까?
sync
저수준 파일 시스템 작업이며 응용 프로그램 수준에서 버퍼링 된 출력과 관련이 없습니다.
sync
필요한 경우 더티 파일 시스템 버퍼를 물리적 스토리지에 기록합니다. 이것은 OS 내부입니다. OS 위에서 실행되는 애플리케이션은 디스크 블록이 물리적 스토리지에 기록되었는지 여부에 관계없이 항상 파일 시스템의 일관된보기를 볼 수 있습니다. 원래 질문에 대해 응용 프로그램 (스크립트)은 아마도 응용 프로그램 내부의 버퍼에 출력을 버퍼링하고 있으며 OS는 출력이 실제로 stdout에 기록 될 예정임을 (아직) 알지 못할 것입니다. 따라서 가상의 "동기화"유형 작업은 스크립트에 "접근"하여 데이터를 가져올 수 없습니다.
Mac OS X의 백그라운드 프로세스에서이 문제가 발생했습니다. StartupItems
. 이것이 내가 그것을 해결하는 방법입니다.
내가 만들면 시작 sudo ps aux
되는 것을 볼 수 있습니다 mytool
.
버퍼링으로 인해 Mac OS X가 종료 mytool
되면 출력이 sed
명령으로 전송되지 않습니다 . 내가 실행하는 경우에는 sudo killall mytool
다음 mytool
받는 출력 전송 sed
명령을 사용합니다. 따라서 Mac OS X가 종료 될 때 실행 되는에 stop
케이스를 추가했습니다 StartupItems
.
start)
if [ -x /sw/sbin/mytool ]; then
# run the daemon
ConsoleMessage "Starting mytool"
(mytool | sed .... >> myfile.txt) &
fi
;;
stop)
ConsoleMessage "Killing mytool"
killall mytool
;;
좋든 싫든 이것이 리디렉션이 작동하는 방식입니다.
귀하의 경우 스크립트의 출력 (스크립트가 완료되었음을 의미)이 해당 파일로 리디렉션됩니다.
원하는 것은 스크립트에 이러한 리디렉션을 추가하는 것입니다.