리디렉션이 실패하면 Bash 프로그램이 실행되지 않습니다 /var/root/log: Permission denied cdal at Mac in ~/experimental/unix_write $

bash에서 리디렉션을 사용하는 명령이 실패하면 그 전에 실행되는 모든 프로그램이 실행되지 않습니다.

예를 들어이 프로그램은 “a”파일을 열고 “a”파일에 50 바이트를 씁니다. 그러나 권한이 충분하지 않은 파일 (~ root / log)로이 명령을 실행하면 파일 크기가 “a”로 변경되지 않습니다.

$ ./write_file.py >> ~root/log
-bash: /var/root/log: Permission denied
cdal at Mac in ~/experimental/unix_write
$ ls -lt
total 16
-rw-rw-r--  1 cdal  staff  0 Apr 27 08:54 a <-- SHOULD BE 50 BYTES

프로그램이 실행되고 모든 출력을 캡처하고 ( “a”파일에 기록), ~ root / log에 출력을 쓰지 못할 것이라고 생각할 것입니다. 대신 프로그램이 실행되지 않습니다.

이것이 왜, bash는 프로그램을 실행하기 전에 수행하는 “검사”순서를 어떻게 선택합니까? 다른 점검도 수행됩니까?

추신 : cron에서 실행되는 프로그램이 “permission denied”파일로 리디렉션 될 때 실제로 실행되었는지 확인하려고합니다.



답변

실제로는 주문 확인의 문제가 아니라 단순히 쉘이 설정하는 순서입니다. 명령이 실행되기 전에 리디렉션이 설정됩니다. 따라서 귀하의 예에서 쉘 ~root/log은 관련 작업을 수행하기 전에 추가를 위해 열려고 시도합니다 ./write_file.py. 로그 파일을 열 수 없으므로 리디렉션이 실패하고 셸이 해당 시점에서 명령 줄 처리를 중지합니다.

이를 입증하는 한 가지 방법은 실행 불가능한 파일을 가져 와서 실행하는 것입니다.

$ touch demo
$ ./demo
zsh: permission denied: ./demo
$ ./demo > ~root/log
zsh: permission denied: /root/log

이것은 쉘이 ./demo리디렉션을 설정할 수없는 시점 조차 보지 못함을 보여줍니다 .


답변

로부터 bash는 남자 페이지, 섹션 재 (내게로 강조) :

명령이 실행 되기 전에 셸이 해석하는 특수 표기법을 사용하여 입력 및 출력을 리디렉션 할 수 있습니다.

파일을 열거 나 만들지 못하면 리디렉션이 실패합니다.

따라서 쉘은의 대상 파일을 열려고 시도 stdout하는데 실패합니다. 명령이 전혀 실행되지 않습니다.


답변

프로그램을 시작하기 전에 쉘 이 경로 재 지정을 설정 해야 한다는 것을 관찰 할 가치가 있습니다.

귀하의 예를 고려하십시오.

./write_file.py >> ~root/log

쉘에서 일어나는 일은 :

  1. 우리 (쉘) fork(); 자식 프로세스는 열린 파일 디스크립터를 부모 (쉘)로부터 상속받습니다.
  2. 자식 프로세스에서 우리는 fopen()“~ root / log”를 확장 dup2()하고 fd 1 (및 close()임시 fd)로 확장합니다. (가) 경우 fopen()실패, 전화를 exit()부모에게 오류를보고 할 수 있습니다.
  3. 여전히 우리는 exec()“./write_file.py”입니다. 이 프로세스는 더 이상 코드를 실행하지 않습니다 (실행에 실패하지 않은 경우 exit()오류를 부모에게보고 함).
  4. 부모는 wait()자식이 종료하고 종료 코드를 ( $?최소한 에 복사하여) 처리하도록합니다 .

리디렉션이 사이의 아동에서 발생하는 그래서 fork()exec(): 그것은 전에 일어날 수 fork()는 쉘의 표준 출력을 변경하지해야하기 때문에, 그것은 이후에 발생할 수 없습니다 exec()파일 이름과 쉘의 실행 코드는 이제 파이썬 프로그램으로 대체 되었기 때문에 . 부모는 자식의 파일 설명자에 액세스 할 수 없습니다 (그렇더라도 exec()stdout으로의 첫 번째 쓰기와 리디렉션 사이를 리디렉션 할 수는 없습니다 ).


답변

그것이 정반대라는 것을 알려 드리게되어 유감입니다. 쉘은 I / O를 먼저 연 다음 제어를 프로그램에 전달해야합니다.

tee 이 경우 도움이 될 수 있습니다. ./write_file.py | tee -a ~root/log > /dev/null