Shebang이 cron에 SHELL을 설정하지 않음

Shebang이 cron에 SHELL을 설정하지 않음

다음을 포함하는 스크립트가 있습니다.

#!/bin/bash
printenv

명령줄에서 실행할 때:

env testscript.sh
bash testscript.sh
sh testscript.sh

매번 출력 SHELL=/bin/bash하지만 cron에서 실행하면 항상 출력됩니다 SHELL=/bin/sh. cron이 shebang을 적용하게 하려면 어떻게 해야 합니까?

크론 경로를 확인했는데 여기에는 /bin이 포함되어 있습니다.

답변1

shebang이 작동 중이며 cron은 그것과 아무 관련이 없습니다. 파일을 실행할 때 파일 내용이 로 시작하면 #!커널은 #!해당 줄에 지정된 파일을 실행하고 원본 파일을 인수로 전달합니다.

SHELL문제는 스크립트가 실행되는 쉘이 쉘 스크립트에 반영된다고 믿는 것 같습니다 . 그렇지 않다. 실제로 대부분의 경우 SHELL사용자의 선호도를 의미합니다.인터렉티브쉘의 역할은 터미널 에뮬레이터와 같은 응용 프로그램이 실행할 쉘을 결정하도록 하는 것입니다. cron에서 SHELLcrontab 항목(시간 표시 뒤의 줄 부분)을 실행하는 데 사용할 프로그램을 cron에 알려주는 변수입니다.

쉘은 SHELL시작 시 설정되지 않는 한 이 변수를 설정하지 않습니다.

사실은 SHELL아마도 /bin/sh관련이 없을 것입니다. 스크립트에는 #!/bin/bash한 줄이 있으므로 bash에 의해 실행됩니다. 확신을 갖고 싶다면 ps $$스크립트를 추가하여 ps스크립트를 실행하는 셸에 대한 정보를 표시하세요.

답변2

배쉬 참조 매뉴얼설명하다:

SHELL - 쉘의 전체 경로 이름이 이 환경 변수에 보관됩니다. 쉘이 쉘 없이 시작되면 Bash는 해당 쉘에 현재 사용자 로그인 쉘의 전체 경로 이름을 할당합니다.

man 5 crontab설명하다:

여러 환경 변수는 cron(8) 데몬에 의해 자동으로 설정됩니다. SHELL은 /bin/sh로 설정되고, LOGNAME 및 HOME은 crontab 소유자의 /etc/passwd 라인에서 설정됩니다. PATH는 "/usr/bin:/bin"으로 설정됩니다. HOME, SHELL 및 PATH는 crontab의 설정으로 재정의될 수 있습니다.

따라서 이 SHELL변수는 Bash가 시작될 때 설정됩니다.

노력하다 SHELL=/bin/awesome/shell bash testcript.sh. 넌 봐야 해SHELL=/bin/awesome/shell

Sherbon이 작동합니다. 당신의 행동이 기록됩니다 :)

답변3

그러나 cron에서 실행하면 항상 SHELL=/bin/sh가 출력됩니다. 왜 이런거야?

이는 cron이 SHELL로 설정되어 있기 때문입니다 /bin/sh. 이는 cron이 crontab 항목을 실행하는 데 사용하는 기본 프로그램이기 때문입니다. 에서 man 5 crontab:

여러 환경 변수는 cron(8) 데몬에 의해 자동으로 설정됩니다. SHELL은 /bin/sh로 설정되어 있습니다...

Evgeny Vereshchagin의 답변이 이미 지적했듯이 변수가 이미 설정되어 있으면 Bash는 나중에 이를 수정하지 않습니다.

cron이 shebang을 적용하게 하려면 어떻게 해야 합니까?

크론은 이미 적용 중입니다.당신의 스크립트를 위해, 다음 예에서 볼 수 있듯이.

다음이 있다고 가정해 보겠습니다 display_process_tree.sh.

#!/bin/bash
pid=$$
depth=0
while
    [ "$pid" -gt 0 ] &&
    read -r ppid name < <(ps -o ppid= -o comm= -p "$pid")
do
    eval $(echo printf '" %0.s"' {0..$depth})
    if [[ -r /proc/$pid/exe ]]; then    
    echo -n "$name - "
    readlink -f /proc/$pid/exe
    else
    echo $name
    fi
    pid=$ppid
    depth=$((depth+1))
done

다음과 같은 crontab도 있습니다.

* * * * * /path/to/display_process_tree.sh > /tmp/display_process_tree.log

이제 출력이 도착할 때까지 기다리면 /tmp/display_process_tree.log다음과 같은 프로세스 트리를 찾을 수 있습니다.

 display_process - /bin/bash
  sh - /bin/dash
   cron
    cron
     systemd

이는 cron이 실제로 /bin/sh스크립트에 대한 /bin/dash새 프로세스를 열기 위해 (내 시스템에 링크된) 사용을 보여줍니다./bin/bash

답변4

shebang을 다음으로 변경하십시오.

#!/bin/env bash

또는 crontab -ecron의 자체 환경 변수가 다르기 때문에 자체 환경 변수를 사용하여 스크립트를 실행하도록 실행합니다.


참고로,에 따르면이 기사는 askubuntu에 있습니다.cron, 스크립트 상단에 PATH를 제공해야 합니다.

PATH=/opt/someApp/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# rest of script follows

그러나 PATH에 올바른 검색 디렉터리가 있는 것 같으면 이를 배제할 수 있습니다.

관련 정보