다음 rc.local
스크립트가 있습니다.
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
sh /home/incero/startup_script.sh
/bin/chmod +x /script.sh
sh /script.sh
exit 0
첫 번째 줄은 startup_script.sh
실제로 세 번째 줄에 언급 된 script.sh
파일을 다운로드합니다 /script.sh
.
불행히도 스크립트를 실행 가능하게 만들거나 실행하지 않는 것으로 보입니다. rc.local
시작한 후 파일을 수동으로 실행하면 완벽하게 작동합니다. 시작할 때 chmod를 실행할 수 없습니까?
답변
빠른 수정 으로 건너 뛸 수 있지만 반드시 최선의 선택은 아닙니다. 먼저이 모든 것을 읽는 것이 좋습니다.
rc.local
오류를 용납하지 않습니다.
rc.local
지능적으로 오류를 복구 할 수있는 방법을 제공하지 않습니다. 명령이 실패하면 실행이 중지됩니다. 첫 번째 줄 #!/bin/sh -e
은 -e
플래그 와 함께 호출 된 쉘에서 실행되도록합니다 . -e
플래그 (이 경우 스크립트를 만드는 것입니다 rc.local
명령이 그 안에 실패 처음 실행을 중지).
당신이 원하는 rc.local
이런 식으로 행동 할 수 있습니다. 명령이 실패하면, 당신은 할 수 없습니다 그것이 다른 시작 명령이 성공하는 데 그것에 의존 될 수 무엇 이건 계속하고 싶다.
따라서 명령이 실패하면 후속 명령이 실행되지 않습니다. 여기서 문제는 /script.sh
실행되지 않은 것입니다 (실패하지 않음, 아래 참조). 실패하기 전에 명령이있을 가능성이 큽니다. 그러나 어느 것?
그렇습니까 /bin/chmod +x /script.sh
?
아니.
chmod
언제든지 잘 작동합니다. 포함 /bin
된 파일 시스템 이 마운트 된 경우을 실행할 수 있습니다 /bin/chmod
. 그리고 달리기 /bin
전에 장착 rc.local
됩니다.
루트로 실행할 때 /bin/chmod
거의 실패하지 않습니다. 작동하는 파일이 읽기 전용 인 경우 실패하며, 파일 시스템이 사용 권한을 지원하지 않으면 실패 할 수 있습니다 . 여기도 없을 것입니다.
그건 그렇고, 실패 하면 실제로 문제 sh -e
가되는 유일한 이유 chmod
입니다. 인터프리터를 명시 적으로 호출하여 스크립트 파일을 실행할 때 파일이 실행 파일로 표시되어 있는지는 중요하지 않습니다. /script.sh
파일의 실행 비트가 중요 하다고 말한 경우에만 . 그것은이라고 말하기 때문에 sh /script.sh
(물론 실행되는 동안 /script.sh
스스로 호출 하지 않는 한 실행 가능한 것이 아니라 실패 할 수는 있지만 스스로 호출하지는 않습니다).
무엇이 실패 했습니까?
sh /home/incero/startup_script.sh
실패한. 거의 확실합니다.
다운로드했기 때문에 실행되었음을 알고 있습니다 /script.sh
.
(그렇지 않으면 경우에 어떻게 든, 그것을 실행 않았다 있는지 확인하는 것이 중요 할 것 /bin
아니 었 PATH – rc.local
반드시 동일하지 않습니다 PATH
. 당신이 로그인 할 때 가지고있는 경우가 /bin
에없는 rc.local
‘의 경로,이 필요 sh
로 실행하는 /bin/sh
. 그것이 실행 않았기 때문에, /bin
에 PATH
, 당신은에있는 다른 명령을 실행할 수 있습니다 의미 /bin
완벽하게 자신의 이름을 미치지 않는. 예를 들어, 당신은 단지 실행할 수 있습니다 chmod
보다는 /bin/chmod
.하지만, 당신의 스타일과 유지에 에서 실행을 제안 할 때마다를 rc.local
제외한 모든 명령에 정규화 된 이름을 사용 sh
했습니다.)
우리는 /bin/chmod +x /script.sh
절대로 실행되지 않을 것이라고 확신 할 수 있습니다 (또는 /script.sh
실행 된 것을 볼 수 있습니다 ). 그리고 우리 sh /script.sh
는 또한 실행되지 않았다는 것을 알고 있습니다.
그러나 그것은 다운로드했다 /script.sh
. 성공했습니다! 어떻게 실패 할 수 있습니까?
성공의 두 가지 의미
명령이 성공했다고 말할 때 두 가지 다른 의미가 있습니다.
- 그것은 당신이 원하는 것을했습니다.
- 성공했다고보고했다.
그리고 그것은 실패를위한 것입니다. 사람이 명령이 실패했다고 말하면 다음을 의미 할 수 있습니다.
- 그것은 당신이 원하는 것을하지 않았습니다.
- 실패했다고보고했습니다.
과 sh -e
같이 스크립트를 실행 rc.local
하면 명령이 처음 실패했다고보고 할 때 실행이 중지됩니다 . 명령이 실제로 수행 한 것과 차이가 없습니다.
당신이 의도하지 않는 한 startup_script.sh
당신이 원하는 것을 할 때 보고서 오류로,이 버그가 있습니다 startup_script.sh
.
- 일부 버그는 스크립트가 원하는 작업을 수행하지 못하게합니다. 이것은 프로그래머가 부작용 이라고 부르는 것에 영향을줍니다 .
- 또한 일부 버그로 인해 스크립트의 성공 여부에 관계없이 스크립트가 올바르게보고되지 않습니다. 프로그래머가 리턴 값 (이 경우 종료 상태 ) 이라고하는 것에 영향을줍니다 .
실패했다고보고 한 것을 제외하고startup_script.sh
는 모든 것을 다 했을 가능성이 높습니다 .
성공 또는 실패보고 방법
스크립트는 0 개 이상의 명령 목록입니다. 각 명령에는 종료 상태가 있습니다. 실제로 스크립트를 실행하는 데 실패가 없다고 가정하면 (예 : 인터프리터가 스크립트를 실행하는 동안 다음 줄을 읽을 수없는 경우) 스크립트의 종료 상태는 다음과 같습니다.
0
(성공) 스크립트가 비어있는 경우 (즉, 명령이없는 경우)N
, 명령의 결과로 스크립트가 종료 된 경우 종료 코드는 어디에 있습니까 ?exit N
N
- 그렇지 않으면 스크립트에서 실행 된 마지막 명령의 종료 코드입니다.
실행 파일이 실행될 때 자체 종료 코드를보고합니다. 스크립트 만이 아닙니다. (기술적으로 스크립트의 종료 코드는 스크립트를 실행하는 셸에서 반환 한 종료 코드입니다.)
예를 들어, C 프로그램이로 끝나 exit(0);
거나 return 0;
그 main()
기능을 수행하는 경우 코드 0
는 운영 체제에 제공되어 호출 프로세스 (예 : 프로그램이 실행 된 쉘일 수 있음)를 제공합니다.
0
프로그램이 성공했음을 의미합니다. 다른 숫자는 모두 실패했음을 의미합니다. (이 방법으로, 다른 숫자는 때때로 프로그램이 실패한 다른 이유를 나타낼 수 있습니다.)
실패한 명령
때로는 실패 할 것이라는 의도로 프로그램을 실행하기도합니다. 이러한 상황에서는 프로그램이 실패를보고하는 버그가 아니지만 실패를 성공으로 생각할 수 있습니다. 예를 들어, rm
이미 존재하지 않는 것으로 의심되는 파일을 삭제했는지 확인하기 위해 사용할 수 있습니다.
startup_script.sh
실행이 중단되기 직전에 이런 일이 일어나고있을 것입니다 . 스크립트에서 실행 되는 마지막 명령 은 실패를보고하는 것입니다 ( “실패”가 완전히 양호하거나 필요한 경우에도 해당).
실패한 테스트
특별한 종류의 명령 중 하나 는 test 인데, 이는 부작용보다는 반환 값에 대한 명령 실행을 의미합니다. 즉, 테스트는 종료 상태를 검사 (및 조치) 할 수 있도록 실행되는 명령입니다.
예를 들어, 4가 5 인 경우를 잊어 버렸다고 가정 해 봅시다.
if [ 4 -eq 5 ]; then
echo "Yeah, they're totally the same."
fi
여기서 테스트 [ -eq 5 ]
는 결국 4 ≠ 5이기 때문에 실패합니다. 그렇다고 테스트가 제대로 수행되지 않았다는 의미는 아닙니다. 그게했다. 4 = 5인지 확인한 다음 성공하면보고하고 그렇지 않은 경우 실패를보고했습니다.
쉘 스크립팅에서 성공은 true 를 의미 하고 실패는 false 를 의미 할 수 있습니다 .
echo
명령문이 실행되지 않더라도 if
전체 블록은 성공을 리턴합니다.
그러나 더 짧게 작성했다고 가정합니다.
[ 4 -eq 5 ] && echo "Yeah, they're totally the same."
이것은 일반적인 속기입니다. &&
A는 부울 및 연산자. &&
로 구성되어 표현, &&
양쪽이 참 (성공)을 반환하지 않는 양쪽에 문장과 거짓 (실패)을 반환합니다. 그냥 정상처럼 하고 .
누군가가 당신에게 묻는다면, “데릭이 쇼핑몰에 가서 나비를 생각하셨습니까?” 데릭이 쇼핑몰에 가지 않았다는 것을 알고 있다면, 나비를 생각하는지 알아낼 필요가 없습니다.
마찬가지로 왼쪽의 명령이 &&
실패하면 (false) 전체 &&
표현식이 즉시 실패합니다 (false). 오른쪽에있는 문장 &&
은 실행되지 않습니다.
여기에, [ 4 -eq 5 ]
실행됩니다. “실패”(거짓을 반환). 따라서 전체 &&
표현이 실패합니다. echo "Yeah, they're totally the same."
절대로 실행되지 않습니다. 모든 것이 정상적으로 동작하지만이 명령은 실패를 보고합니다 ( if
위의 조건 과 동등한 조건이 성공 하더라도 ).
이것이 스크립트의 마지막 문장 (그리고 스크립트가 어느 시점 이전에 종료되지 않고 스크립트에 도달 한 경우)이면 전체 스크립트는 failure를 보고 합니다.
이 외에도 많은 테스트가 있습니다. 예를 들어, ||
( “또는”) 테스트가 있습니다. 그러나 위의 예제는 테스트가 무엇인지 설명하기에 충분해야하며 문서를 효과적으로 사용하여 특정 명령문 / 명령이 테스트인지 판별 할 수 있습니다.
sh
vs. sh -e
, 재 방문
이후 라인 (참조 : 이 질문 의 상단에있는) 가 이 명령을 호출하는 것처럼 운영 시스템은 스크립트를 실행합니다 :#!
/etc/rc.local
sh -e
sh -e /etc/rc.local
대조적으로와 같은 다른 스크립트 는 플래그 없이startup_script.sh
실행 됩니다-e
.
sh /home/incero/startup_script.sh
결과적으로 명령이 실패를보고하더라도 계속 실행됩니다.
이것은 정상적이고 좋습니다. rc.local
로 실행해야하며 sh -e
대부분의 다른 스크립트 (예 : 대부분의 스크립트 포함)는 rc.local
호출하지 않아야합니다.
차이점을 기억하십시오.
-
스크립트에
sh -e
포함 된 명령 이 종료보고 실패를 처음 시작할 때 스크립트는 종료보고 실패로 실행 됩니다.마치 스크립트가
&&
연산자 와 결합 된 스크립트의 모든 명령으로 구성된 단일 긴 명령 인 것처럼 보입니다. -
sh
(없이-e
) 스크립트는 스크립트 를 종료 (종료)하는 명령이 나올 때까지 또는 스크립트가 끝날 때까지 계속 실행됩니다. 모든 명령의 성공 또는 실패는 본질적으로 관련이 없습니다 (다음 명령이 확인하지 않는 한). 스크립트는 마지막 명령 실행의 종료 상태로 종료됩니다.
스크립트가 결국 실패가 아님을 이해하도록 돕는 것
실패했을 때 스크립트가 실패했다고 생각하지 않게하려면 어떻게해야합니까?
당신은 실행이 끝나기 직전에 무슨 일이 일어나는지 봅니다.
-
명령이 성공했을 때 실패한 경우 이유를 파악하고 문제를 해결하십시오.
-
명령이 실패했고 이것이 올바르게 발생했다면 해당 실패 상태가 전파되는 것을 방지하십시오.
-
실패 상태가 전파되지 않도록하는 한 가지 방법은 성공한 다른 명령을 실행하는 것입니다.
/bin/true
부작용이 없으며 성공을보고합니다 (/bin/false
아무것도하지 않고 실패 함). -
다른 하나는로 스크립트를 종료시키는 것
exit 0
입니다.그것은 반드시
exit 0
스크립트의 끝에 있는 것과 반드시 같은 것은 아닙니다 . 예를 들어,if
스크립트가 내부에서 종료 되는 -block 이있을 수 있습니다 .
-
성공을보고하기 전에 스크립트가 실패를보고하는 원인을 아는 것이 가장 좋습니다. 실제로 어떤 방식 으로든 실패한 경우 (원하는 작업을 수행하지 않는다는 의미에서) 성공을보고하기를 원하지 않습니다.
빠른 수정
startup_script.sh
엑시트보고 성공을 할 수없는 경우 , rc.local
실행 보고 명령을 변경하여 명령이 실패하더라도 성공을 보고 할 수 있습니다 startup_script.sh
.
현재 당신은 :
sh /home/incero/startup_script.sh
이 명령은 동일한 부작용 (예 : running의 부작용 startup_script.sh
)이 있지만 항상 성공을보고합니다.
sh /home/incero/startup_script.sh || /bin/true
startup_script.sh
보고서가 실패한 이유를 알고 수정하는 것이 좋습니다.
빠른 수정의 작동 방식
이것은 실제로 ||
테스트, 또는 테스트 의 예입니다 .
내가 쓰레기를 꺼내거나 부엉이를 닦았는지 물어 보자. 쓰레기를 꺼내면 올빼미를 닦았는지 여부를 기억하지 않아도 진실로 “예”라고 말할 수 있습니다.
왼쪽에있는 명령이 ||
실행됩니다. 성공하면 (true) 오른쪽을 실행할 필요가 없습니다. 따라서 startup_script.sh
성공을보고하면 true
명령 이 실행되지 않습니다.
그러나 startup_script.sh
실패를보고 하면 (쓰레기를 꺼내지 않았다) , /bin/true
[부엉이를 닦으면] 의 결과가 중요합니다.
/bin/true
항상 성공을 반환합니다 (또는 때때로 호출하기 때문에 true ). 결과적으로 전체 명령이 성공하고 다음 명령 rc.local
이 실행될 수 있습니다.
성공 / 실패, 참 / 거짓, 0 / 제로에 대한 추가 참고 사항.
이것을 무시하십시오. 그러나 둘 이상의 언어로 프로그래밍하는 경우 (예를 들어 쉘 스크립팅이 아니라)이를 읽을 수 있습니다.
C와 같은 프로그래밍 언어를 사용하는 쉘 스크립터와 쉘 스크립팅을 사용하는 C 프로그래머는 다음을 발견하는 데 큰 혼란이 있습니다.
-
쉘 스크립팅에서 :
- 반환 값은 success 및 / 또는 true 를
0
의미 합니다 . - 이외의 반환 값은 failure 및 / 또는 false를
0
의미 합니다.
- 반환 값은 success 및 / 또는 true 를
-
C 프로그래밍에서 :
- 반환 값은 false 를
0
의미합니다 . - 이외의 반환 값은 true를
0
의미 합니다 . - 성공의 의미와 실패의 의미에 대한 간단한 규칙은 없습니다. 때로는
0
성공, 다른 경우는 실패, 다른 경우는 방금 추가 한 두 숫자의 합이 0임을 의미합니다. 일반 프로그래밍에서 반환 값은 다양한 종류의 정보를 알리는 데 사용됩니다. - 프로그램의 숫자 종료 상태는 쉘 스크립팅 규칙에 따라 성공 또는 실패를 표시해야합니다. 즉,
0
C 프로그램에서 false를 의미 하더라도 프로그램0
이 성공했다고보고하려면 프로그램 이 종료 코드로 리턴하게합니다 (쉘이 true 로 해석 함 ).
- 반환 값은 false 를
답변
유닉스 변형에서 다음을 변경하여 기본 동작을 무시할 수 있습니다.
#!/bin/sh -e
에:
#!/bin/sh
스크립트 시작시 “-e”플래그는 sh에게 첫 번째 오류 발생시 종료하도록 지시합니다. 이 플래그의 긴 이름은 “errexit”이므로 원래 줄은 다음과 같습니다.
#!/bin/sh --errexit
답변
첫 번째 줄에서 변경 :
#!/bin/sh -e
에
!/bin/sh -e