at 작업은 #!/bin/bash가 있음에도 불구하고 /bin/sh를 사용하여 실행 중인 것 같습니다.

at 작업은 #!/bin/bash가 있음에도 불구하고 /bin/sh를 사용하여 실행 중인 것 같습니다.

을 사용하여 작업을 실행하려고 하는데 스크립트 at가 있습니다 bash(첫 번째 줄이 있음). 그러나 스크립트 내에서 사용하면 #!/bin/bash작업이 실패하므로 생성된 스크립트에서 다음이 표시됩니다.[[]]mail

=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found
=sh: 58: [[: not found

여기에 /bin/sh링크가 있습니다 dash. 하지만 내 스크립트에 she-bang 줄이 있으면 #!/bin/bash그것을 사용하면 안 되나요 bash?

PS 프롬프트에서 스크립트를 실행하면 bash오류 없이 잘 작동합니다(실행 권한도 있음).

- 편집하다 -

다음과 같이 작업을 추가합니다.

$ at 1:30 am today -f /path/to/my/script.sh



$ which bash 
/bin/bash

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Mar 30  2012 /bin/sh -> dash

$ uname -a
Linux server1 3.5.0-46-generic #70~precise1-Ubuntu SMP Thu Jan 9 23:55:12 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux

답변1

POSIX는 정의합니다존재하다사용할 수 있다껍데기대안으로 환경 변수를 사용 /bin/sh하지만 이에 국한되지는 않습니다.

껍데기

at-job을 호출하는 데 사용되는 명령 해석기의 이름을 결정합니다. 변수가 설정되지 않았거나 비어 있으면 sh를 사용해야 합니다. sh 이름 이외의 값으로 설정된 경우 구현은 다음 중 하나를 수행해야 합니다. 해당 쉘을 사용하고, 사용자 데이터베이스에서 로그인 쉘을 사용하거나 선택된 경고 진단을 동반합니다.

-kat의 일부 구현에서는 Korn 쉘, -cC-쉘 과 같이 실행할 쉘을 선택할 수 있습니다 . 그리고 모든 구현이 대체를 at허용하는 것은 아닙니다 . 따라서 POSIX는 또한 다른 쉘을 사용하는 안정적인 방법이 다음과 같다는 것을 보장합니다.SHELLsh명시적으로 호출:

일부 구현에서는 SHELL을 다른 쉘 대신 사용할 수 없습니다. 예를 들어, System V 시스템은 이미 /etc/passwd에서 사용자의 로그인 셸 값을 사용하고 있습니다. 다른 명령 해석기를 안정적으로 선택하려면 사용자가 이를 스크립트의 일부로 포함해야 합니다. 예:

$1800

마이쉘 마이스크립트

산화 에틸렌

일...에서...$

간단한 방법은 stdin으로 전달된 bash실행 스크립트를 bash script다음과 같이 사용하는 것입니다 at.

echo "bash /path/to/yourscript" | at <time>

예:

echo "bash /path/to/yourscript" | at 16:30

bash /path/to/yourscript오늘 16시 30분에 실행됩니다.

답변2

at그리고batch:

표준 입력이나 지정된 파일에서 나중에 실행할 명령을 읽으려면 /bin/sh를 사용하십시오.

POSIX 정의 at입력처럼:

다음에 설명된 쉘 명령 언어에 허용되는 명령으로 구성된 텍스트 파일쉘 명령 언어.

즉, 그것은필수의POSIX sh스크립트가 됩니다. Bash는 bash로 실행되더라도 bashism을 통과하도록 허용 sh하지만 dash매우 엄격합니다. 스크립트는 실행 파일로 실행되지 않고 run 을 사용하여 직접 실행되므로 sh임의의 바이너리나 Python 스크립트를 실행할 수 없습니다.


하지만 당신이 할 수 있는 일은 bash무슨 일이 있어도 스스로를 강요하는 것입니다. 그것은 다음과 같습니다:

[ "$BASH_VERSION" ] || exec bash "/path/to/script"

파일 상단에서 bash스크립트가 이런 방식으로 해석되지 않은 경우 스크립트가 자체적으로 다시 실행되도록 해야 합니다. 셸은 실행 시 도달하지 않은 코드에 대해 구문 오류를 생성하지 않으므로 나중에 사용해도 [[문제가 되지 않습니다. $0경로 대신 사용할 수도 있지만 at구현 간에 일관성이 없는 것으로 보이며 경로가 더 안정적일 수 있도록 작동해야 한다는 사양이 없습니다.

답변3

내 대답은 Gnouc의 대답과 비슷하지만 "왜?"에 대한 더 나은 설명이 있다고 생각합니다. 당신이 그렇게 말할 때 at … -f /path/to/my/script.sh, 당신은 at읽으라고 말하고 있는 것입니다 /path/to/my/script.sh. 작업 데몬이 스크립트 내용을 에 전달할 수 /var/spool/cron있도록 스크립트를 어딘가(아마도 아래)에 복사합니다 . 이 시점에서 셔뱅라인은 단지 코멘트일 뿐이고 사용법 이 잘못되었습니다.atdat/bin/sh#!/bin/bash[[…]]

당신이하고 싶은 것은 at주는 것이 아닙니다콘텐츠당신의 대본을 줘이름, 통과

$ echo /path/to/my/script.sh | at 1:30 am today

또는

오늘 아침 1시 30분 $
/경로/to/my/script.sh
Ctrl+D

이렇게 하면 명령으로 /bin/sh보고 실행됩니다. /path/to/my/script.sh그리고그 다음에she-bang 라인이 그 역할을 수행하여 bash호출됩니다.

atdPS 내 답변(Gnouc과 같은) 에는 지금부터 오늘 오전 1시 30분 사이에 스크립트를 변경하면 수정된 버전을 실행하는 "기능"이 있습니다 . (이는 를 사용하여 런타임 시 스크립트의 복사본을 만드는 -f접근 방식과 대조됩니다 .) 특히 스크립트를 삭제하거나 이름을 바꾸면 아무 것도 실행되지 않습니다.atat

관련 정보