두 디렉터리에서 파일 목록을 가져와서 차이점을 파악하고 특정 파일에 대해 일부 코드를 실행하는 스크립트가 있습니다.
다음은 파일 목록을 가져오는 명령입니다.
list_in=$(find input/ -maxdepth 1 - type f | sed 's/input\///' | sort -u);
list_out=$(find output/ -maxdepth 1 - type f | sed 's/output\///' | sort -u);
올바른 디렉터리에서 스크립트를 실행 중이므로 실패해서는 안 됩니다. 처리되지 않은 파일은 다음에 의해 결정됩니다.
list_todo=$(comm -23 <(echo "$list_in") <(echo "$list_out"));
옵션은 -23
첫 comm
번째 인수에 대한 행만 인쇄하므로 해당 행은 두 인수 모두에 표시되지 않으며 두 번째 인수에 고유하게 나타나는 행은 인쇄되지 않습니다.
그러나 가끔 오류 메시지가 나타납니다.
command substitution: line 3: syntax error near unexpected token `('
command substitution: line 3: `comm -23 <(echo "$list_in") <(echo "$list_out")'
지난 3주 동안 똑같은 스크립트가 제대로 작동했기 때문에 이것은 나를 정말 혼란스럽게 합니다. 나는 이것을 클러스터에서 사용하고 있으므로 여러 프로세스가 동시에 스크립트를 실행할 수 있습니다. 이로 인해 오류가 발생할 수 있습니까?
고쳐 쓰다. 스크립트는 via로 호출되며 ./script
분명히 이전에 설정했습니다 chmod +x script
.
(면책조항: 클러스터에서 작업 중이고 스크립트의 처음 세 줄에 잠금 메커니즘이 포함되어 있지 않더라도 파일은 두 번 처리되지 않습니다.)
답변1
커널은 기본적으로 실행될 수 있는 특정 파일 형식을 인식합니다. 여기에는 하나 이상의 이진 형식이 포함됩니다. 게다가 #!
(셰르본)은 스크립트로 처리됩니다. 예를 들어 파일이 에 있고 /path/to/script
로 시작하는 경우 호출할 때 커널이 실행됩니다 #!/bin/bash
./bin/bash /path/to/script arg1 arg2
/path/to/script arg1 arg2
커널이 파일 형식을 인식하지 못하면 파일에서 ENOEXEC(Execution Format Error)가 반환됩니다.execve
시스템 호출. Shebang 기능이 없는 Unix 커널의 고대 전통에 따라 대부분의 프로그램은 ENOEXEC 오류와 함께 첫 번째 시도가 실패할 때 프로그램을 다시 실행하려고 시도합니다. 즉, /bin/sh
스크립트 인터프리터로 실행을 시도합니다.
Bash는 주목할 만한 예외입니다. Bash는 NET이 아닌 자체적으로 스크립트를 실행합니다 /bin/sh
. 따라서 Bash에서 호출하면 스크립트가 예기치 않게 작동합니다.
shebang 줄을 생략하면 스크립트를 실행하는 프로그램에 따라 스크립트가 /bin/bash
아래 또는 아래에서 실행될 수 있습니다. /bin/sh
그리고 /bin/sh
분명히 시스템의 프로세스 교체는 지원되지 않습니다. 여전히 bash일 수 있지만(오류 메시지는 bash의 오류 메시지처럼 보임) 이름으로 bash를 호출하면 sh
프로세스 대체를 지원하지 않는 POSIX 호환 모드로 전환됩니다.
이야기의 교훈은 다음과 같습니다. bash 스크립트를 작성하려면 이를 #!/bin/bash
첫 번째 줄에 배치해야 합니다.
답변2
$() 및 <() 구성은 bash에서만 작동합니다. 이는 shebang 줄을 다음과 같이 설정해야 함을 의미합니다.
#!/bin/bash
특히 이것은 것입니다아니요일하다:
#!/bin/sh
작동하기 위해 필요한 경우 sh
$() 대신 `를 사용할 수 있습니다.
list_in=`find input/ -maxdepth 1 - type f | sed 's/input\///' | sort -u`
<() 대신 mkfifo를 사용할 수 있습니다.