모든 출력을 폴더에 기록하는 cron 래퍼를 작성하고 싶습니다 $CRON_LOG_DIR
.
사용법은 다음과 같습니다.
* * * * * $CRON_WRAPPER "<job name>" "command"
stdout
그러면 다음 stderr
의 전체 출력이 기록됩니다 command
.
$CRON_LOG_DIR/<date>/<job_name>/command_timestamp.log
아래 스크립트를 사용하고 있지만 $CRON_WRAPPER
명령이 여러 명령으로 구성된 사례는 기록되지 않는 것 같습니다 stdout
.command
* * * * * $CRON_WRAPPER "<job name>" "command1 && command2 && command3"
왜?
아래는 전체 내용입니다CRON_WRAPPER
#!/usr/bin/env zsh
COMMAND_NAME=$1
shift
DATE=$(date +%B_%d_%Y)
TIMESTAMP=$(date +%Y-%m-%d_%H-%M-%S)
THIS_CRON_LOG_DIR=$CRON_LOG_DIR/$DATE
mkdir -p $THIS_CRON_LOG_DIR
CRON_LOG_FILE=${THIS_CRON_LOG_DIR}/${COMMAND_NAME}_${TIMESTAMP}.log
# Joining commands:
to_join=$@
joined=$(printf ",%s" "${to_join[@]}")
# Redirecting all output to our logging file:
joined=${joined:1}">> $CRON_LOG_FILE 2>&1"
# Finally evaluating the command
eval $joined
답변1
스크립트의 첫 번째 인수가 이고 jobname
두 번째 인수가 인 command1 && command2 && command3
경우 변수에 빌드하는 명령은 joined
다음과 같습니다.
command1 && command2 && command3>> /path/to/cron/log/dir/May_12_2015/jobname_2015-05-12_01-09-25.log 2>&1
이 문자열을 호출하면 eval
정상적으로 구문 분석됩니다. 리디렉션은 "command3"에서만 작동합니다.
두 번째 인수를 쉘 조각의 접두사가 아닌 쉘 조각으로 처리하려고 합니다. 그러니 그것에 연결하지 마십시오. 리디렉션은 eval
구문 분석해야 하는 문자열을 통하지 않고 스크립트에서 직접 지정하므로 아래가 아닌 스크립트에 직접 속합니다. 셸 특수 문자를 포함 하면 jobname
코드가 중단됩니다. 예를 들어 $CRON_WRAPPER $(touch /tmp/foo) stuff
코드가 실행됩니다 touch /tmp/foo
.
스크립트의 또 다른 문제점은 매개변수가 2개 이상일 경우 매개변수 사이에 쉼표가 추가된다는 점입니다. 이는 의미가 없습니다. 공백으로 연결하는 것이 더 합리적일 것입니다 "$*
. 간단합니다 . (지금 하고 있는 작업은 쉼표를 구분 기호로 사용하여 연결하기에는 지나치게 복잡합니다. zsh에서는 ${(j:,:)@}
.)
# Joining commands:
다음으로 시작하는 스크립트 부분을 바꿉니다.
eval "$*" >>$CRON_LOG_FILE 2>&1