환경 cron을 시뮬레이션하는 방법은 다음과 함께 스크립트를 실행합니까?


253

일반적으로 환경 설정이 없으므로 cron에서 스크립트를 실행하는 방법에 몇 가지 문제가 있습니다. cron과 동일한 방식으로 bash (?)를 호출하는 방법이 있으므로 스크립트를 설치하기 전에 테스트 할 수 있습니까?



: 조금 더 @gregseth 촬영,이 솔루션했다 unix.stackexchange.com/questions/27289/...
로버트 Brisita

답변:


385

이것을 crontab에 추가하십시오 (일시적으로).

* * * * * env > ~/cronenv

실행 후 다음을 수행하십시오.

env - `cat ~/cronenv` /bin/sh

이것은 cron이 / bin / sh를 실행한다고 가정합니다. 이는 사용자의 기본 쉘에 관계없이 기본값입니다.


5
참고 : 전역 / etc / crontab에 추가하면 사용자 이름도 필요합니다. 예를 들어 * * * * * root env> ~ / cronenv
Greg Greg

10
좋은 아이디어입니다. 초조 한 사용을 위해 '* * * * *'를 사용하여 다음 순간에 실행하고 ;-) 연주가 끝나면 다시 꺼야합니다.
Mads Buus

5
@Madsn 이전 bash 쉘로 돌아가려면 : exit
spkane

5
이 답변의 중요성을 과소 평가할 수 없습니다. 책에 단락을 포함시킬만한 가치가 있습니다.
Xofo

1
되는 env - 고양이 ~ / cronenv` / 빈 / sh`은 cron 작업으로 작성해야 하는가? 예를 들어주세요
JavaSa

61

Cron은 기본적으로이 환경 만 제공합니다.

  • HOME 사용자의 홈 디렉토리
  • LOGNAME 사용자의 로그인
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh

더 필요한 경우 crontab의 스케줄링 테이블 전에 환경을 정의하는 스크립트를 소싱 할 수 있습니다.


7
.보안상의 이유로 일반적으로 PATH더 이상 포함 되지 않습니다 .
l0b0

49

몇 가지 접근 방식 :

  1. cron env를 내보내고 가져옵니다.

    더하다

    * * * * * env > ~/cronenv

    crontab에 한 번 실행 한 다음 다시 끈 다음 실행하십시오.

    env - `cat ~/cronenv` /bin/sh

    그리고 당신은 이제 shcron의 환경을 가진 세션 안에 있습니다.

  2. cron에 환경을 가져 오십시오

    당신은 위의 운동을 건너 뛸 수 있고 . ~/.profilecron 작업 앞에서 할 수 있습니다.

    * * * * * . ~/.profile; your_command
  3. 화면 사용

    이 개 솔루션은 여전히 그들에 접근, 실행중인 X 세션에 연결된 환경을 제공하는 것을 실패보다도 dbus우분투에 예를 들어 등 nmcli(네트워크 관리자) 두 가지 방법 이상에서 작동하지만 여전히 크론에 실패합니다.

    * * * * * /usr/bin/screen -dm

    cron에 위의 줄을 추가하고 한 번 실행 한 다음 다시 끕니다. 화면 세션에 연결하십시오 (screen -r). 화면 세션을 확인하는 경우 (함께 생성 된 ps그들이 자본에 때때로 (예를 것을 인식) ps | grep SCREEN)

    이제는 짝수 nmcli와 비슷한 것이 실패합니다.


22

당신은 실행할 수 있습니다 :

env - your_command arguments

빈 환경에서 your_command를 실행합니다.


4
cron이 완전히 빈 환경에서 실행되지 않습니까?
jldupont

2
gregseth는 환경에 포함 된 변수를 cron으로 식별했습니다. 해당 변수를 명령 행에 포함시킬 수 있습니다. $ env-PATH = "$ PATH"명령 인수
DragonFax

4
@DragonFax @dimba 나는 env - HOME="$HOME" LOGNAME="$USER" PATH="/usr/bin:/bin" SHELL="$(which sh)" command arguments트릭을 수행하는 것으로 보인다
l0b0

이것은 "적대적인"환경이나 알 수없는 환경에서 스크립트를 테스트하기위한 아주 간단한 방법입니다. 당신이 이것에서 실행될 정도로 명백하다면, 그것은 cron에서 실행될 것입니다.
Oli


13

6 년 후 답변 : 환경 불일치 문제는 systemd"타이머"가 cron 대체품으로 해결 한 문제 중 하나입니다 . CLI 또는 cron을 통해 시스템화 된 "서비스"를 실행하든 환경 불일치 문제를 피하면서 정확히 동일한 환경을 수신합니다.

cron 작업이 수동으로 전달 될 때 실패하는 가장 일반적인 문제는 $PATHcron에서 설정 한 제한적인 기본값 이며, 이는 Ubuntu 16.04에서 발생합니다.

"/usr/bin:/bin"

대조적 으로 Ubuntu 16.04에서 $PATH설정 한 기본값 systemd은 다음과 같습니다.

"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

따라서 시스템 타이머가 더 이상 번거 로움없이 바이너리를 찾을 가능성이 이미 높습니다.

시스템 타이머의 단점은 설정 시간이 조금 더 있다는 것입니다. 먼저 "서비스"파일을 작성하여 실행할 항목을 정의하고 "타이머"파일을 실행하여 스케줄을 정의한 후 타이머를 "활성화"하여 활성화하십시오.


10

env를 실행하고 stdout을 파일로 경로 재지 정하는 cron 작업을 작성하십시오. "env-"와 함께 파일을 사용하여 cron 작업과 동일한 환경을 작성하십시오.


죄송합니다. 혼란 스럽습니다. "env-script"가 충분하지 않습니까?
Jorge Vargas

그것은 당신에게 빈 환경을 줄 것입니다. cron을 통해 스크립트를 실행할 때 환경이 비어 있지 않습니다.
Jens Carlberg


2

기본적으로 cron시스템의 아이디어가 무엇이든간에 작업을 실행합니다 sh. 이것은 실제 Bourne 쉘 수 또는 수 dash, ash, ksh또는 bash(또는 다른)에 심볼릭 링크 sh(및 POSIX 모드에서 실행 결과로).

가장 좋은 방법은 스크립트에 필요한 내용이 있는지 확인하고 아무것도 제공하지 않는다고 가정하는 것입니다. 따라서 전체 디렉토리 스펙을 사용하고 $PATH자신 과 같은 환경 변수를 설정해야합니다 .


이것은 내가 해결하려고하는 것입니다. 실수로 무언가를 가정하는 스크립트에는 수많은 문제가 있습니다. 전체 경로를 수행하고 환경 변수와 모든 정크를 설정하면 끔찍한 거대한 유지 불가능한 크론 라인으로 끝납니다
Jorge Vargas

re * sh 죄송합니다 .bash = shell로 자랐으므로 대안 (그리고 때로는 더 나은) 쉘을 기억하기가 어렵습니다.
Jorge Vargas

1
@ 조지 : crontab의 줄은 상당히 짧아야합니다. 스크립트 (또는 래퍼 스크립트) 내에서 필요한 모든 설정을 수행해야합니다. 예를 들어 crontab의 일반적인 행은 다음과 같습니다. 0 0 * * 1 /path/to/executable >/dev/null 2>&1그런 다음 "실행 가능"내 $PATH에서 등의 값을 설정 하고 전체 디렉토리 스펙을 사용하여 파일을 입력 및 출력하는 등의 작업을 수행합니다. 예를 들면 다음과 같습니다./path/to/do_something /another/path/input_file /another/path/to/output_file
추가 통지가있을 때까지 일시 중지되었습니다.

1

내가 찾은 또 다른 간단한 방법 (그러나 오류가 발생하기 쉬울 수도 있지만 테스트 중임)은 명령 전에 사용자의 프로필 파일을 제공하는 것입니다.

/etc/cron.d/ 스크립트 편집 :

* * * * * user1 comand-that-needs-env-vars

로 변할 것입니다 :

* * * * * user1 source ~/.bash_profile; source ~/.bashrc; comand-that-needs-env-vars

더럽지 만 작업이 완료되었습니다. 로그인을 시뮬레이트하는 방법이 있습니까? 실행할 수있는 명령 만? bash --login작동하지 않았다. 그래도 더 좋은 방법이 될 것 같습니다.

편집 : 이것은 확실한 해결책 인 것 같습니다 : http://www.epicserve.com/blog/2012/feb/7/my-notes-cron-directory-etccrond-ubuntu-1110/

* * * * * root su --session-command="comand-that-needs-env-vars" user1 -l

1

허용되는 답변은 cron이 사용할 환경에서 스크립트를 실행하는 방법을 제공합니다. 다른 사람들이 지적했듯이, 이것은 cron 작업을 디버깅하는 데 필요한 유일한 기준은 아닙니다.

실제로 cron은 입력 등이없는 비 대화식 터미널도 사용합니다.

그것이 도움이된다면, cron에 의해 실행될 때 명령 / 스크립트를 고통없이 실행할 수있는 스크립트를 작성했습니다. 첫 번째 인수로 명령 / 스크립트를 사용하여 호출하면 좋습니다.

이 스크립트는 Github 에서도 호스팅되고 업데이트 될 수 있습니다 .

#!/bin/bash
# Run as if it was called from cron, that is to say:
#  * with a modified environment
#  * with a specific shell, which may or may not be bash
#  * without an attached input terminal
#  * in a non-interactive shell

function usage(){
    echo "$0 - Run a script or a command as it would be in a cron job, then display its output"
    echo "Usage:"
    echo "   $0 [command | script]"
}

if [ "$1" == "-h" -o "$1" == "--help" ]; then
    usage
    exit 0
fi

if [ $(whoami) != "root" ]; then
    echo "Only root is supported at the moment"
    exit 1
fi

# This file should contain the cron environment.
cron_env="/root/cron-env"
if [ ! -f "$cron_env" ]; then
    echo "Unable to find $cron_env"
    echo "To generate it, run \"/usr/bin/env > /root/cron-env\" as a cron job"
    exit 0
fi

# It will be a nightmare to expand "$@" inside a shell -c argument.
# Let's rather generate a string where we manually expand-and-quote the arguments
env_string="/usr/bin/env -i "
for envi in $(cat "$cron_env"); do
   env_string="${env_string} $envi "
done

cmd_string=""
for arg in "$@"; do
    cmd_string="${cmd_string} \"${arg}\" "
done

# Which shell should we use?
the_shell=$(grep -E "^SHELL=" /root/cron-env | sed 's/SHELL=//')
echo "Running with $the_shell the following command: $cmd_string"


# Let's route the output in a file
# and do not provide any input (so that the command is executed without an attached terminal)
so=$(mktemp "/tmp/fakecron.out.XXXX")
se=$(mktemp "/tmp/fakecron.err.XXXX")
"$the_shell" -c "$env_string $cmd_string" >"$so" 2>"$se" < /dev/null

echo -e "Done. Here is \033[1mstdout\033[0m:"
cat "$so"
echo -e "Done. Here is \033[1mstderr\033[0m:"
cat "$se"
rm "$so" "$se"

0

답변 https : //.com/a/2546509/5593430 은 cron 환경을 얻는 방법과 스크립트에 사용하는 방법을 보여줍니다. 그러나 사용하는 crontab 파일에 따라 환경이 다를 수 있습니다. 를 통해 환경을 저장하기 위해 세 가지 다른 cron 항목을 만들었습니다 env > log. Amazon Linux 4.4.35-33.55.amzn1.x86_64의 결과입니다.

1. 루트 사용자가있는 전역 / etc / crontab

MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
PWD=/
LANG=en_US.UTF-8
SHLVL=1
HOME=/
LOGNAME=root
_=/bin/env

2. 루트 사용자 crontab ( crontab -e)

SHELL=/bin/sh
USER=root
PATH=/usr/bin:/bin
PWD=/root
LANG=en_US.UTF-8
SHLVL=1
HOME=/root
LOGNAME=root
_=/usr/bin/env

3. /etc/cron.hourly/의 스크립트

MAILTO=root
SHELL=/bin/bash
USER=root
PATH=/sbin:/bin:/usr/sbin:/usr/bin
_=/bin/env
PWD=/
LANG=en_US.UTF-8
SHLVL=3
HOME=/
LOGNAME=root

가장 중요한 것은 PATH, PWD과는 HOME다르다. 안정적인 환경에 의존하도록 cron 스크립트에서이를 설정하십시오.


-8

나는 믿지 않는다. cron 작업을 테스트하는 유일한 방법은 나중에 1-2 분 동안 실행하도록 설정 한 다음 기다리는 것입니다.


이것이 제가 시뮬레이션을 요청하는 이유입니다
Jorge Vargas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.