프로그래밍 방식으로 crontab에 무언가 추가하기 (ssh 이상)


13

배포 스크립트가 있는데 사용자에게 무언가를 추가해야합니다 crontab(XXX 일마다 로그를 정리하는 스크립트를 트리거 함). 이는 첫 번째 배포 중 또는 업데이트가 필요한 경우에만 수행해야합니다.

( xxx.py deploy env또는 달리기 가능 xxx.py update env)

그래서 나는 이것을해야합니다 :

Check if my cronJob already exist
Put my cronJob if it does not already exist
or
update my cronjob if one of the parameter of the command is different

파일 crontab을 사용 crontab -e하거나 편집 하지 않고 무언가를 추가 / 확인 / 제거하는 방법을 볼 수 없습니다 crontab(다운로드, 다시 작성, 다시 업로드)

추신 : 이것은 사용자 별 cronjob이며, "webadmin"은 그것을 할 것이며 sudo를 사용해서는 안됩니다.


1
사용자 별 crontab에 있어야합니까? 사전 패키지 된 대부분의 크론 작업은 /etc/cron.* 디렉토리 중 하나로 이동합니다.
CVn

CentOS가 /etc/cron.d있습니까? 그렇다면 응용 프로그램에 고유 한 이름을 사용하여 스크립트를 작성하십시오.
roaima

예, 사용자별로 다릅니다. 루트 파일이기 때문에 /etc/cron.d에 추가 할 수 없습니다. 따라서 루트 작업 만 내부에서 느려집니다 (sudo는 가능하지만 나쁜 연습을 들었습니다)
sliders_alpha

1
와 마찬가지로 /etc/crontab파일의 파일 /etc/cron.d/은 일정 사양 직후에 사용자 이름에 대한 추가 필드가 있습니다. 예 * * * * * username /path/to/script. man 5 crontab를 검색 하십시오 SYSTEM CRON.
cas

답변:


15

지금까지 내 최고의 아이디어

내용이 내용과 일치하는지 먼저 확인하고 내용이 일치하지 않는 경우에만 업데이트하십시오.

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    echo $(crontab -l ; echo '* 1 * * * some_command') | crontab -
fi

그러나 이것은 cron 작업을 중심으로 별도의 스크립트를 작성하기에 충분히 복잡해집니다.

다른 아이디어

stdin을 통해 문자열을 crontab으로 보낼 수 있습니다 (이것은 이전 crontab 항목을 지 웁니다).

echo "* 1 * * * some_command" | crontab -

이것은 ssh를 통해 올바르게 작동해야합니다.

echo "* 1 * * * some_command" | ssh user@host "crontab -"

파일에 추가하려면 다음을 사용할 수 있습니다.

# on the machine itself
echo "$(echo '* 1 * * * some_command' ; crontab -l)" | crontab -
# via ssh
echo "$(echo '* 1 * * * some_command' ; ssh user@host crontab -l)" | ssh user@host "crontab -"

거기에 따라 : 거기에 있었을 것이 필요합니까? :)
Phillip -Zyan K Lee- Stockmann

아 ... ... 루트로 실행되지 않습니까? ... 나는 그것을 다시 쓸 것이다 ...
Phillip -Zyan K Lee- Stockmann

eh, 나는 그것을 좋아한다 : D
sliders_alpha

이 솔루션에는 두 가지 문제가 있습니다. 1) 파일 목록으로 echo '*...확장했습니다 *. 2) crontab의 줄 끝이 삭제되었습니다.
Heath Raftery

나는이 문제를 1) 변경으로 바꾸고 echo "*...2) echo $줄의 시작 부분에서 제거 하여 해결할 수있었습니다 .
Heath Raftery

3

기록을 위해을 사용하는 것이 좋습니다 /etc/cron.d/. 여기서는 root 만 파일을 쓸 수 있지만 항목은 모든 사용자로 실행할 수 있습니다 (필요 없음 sudo).

echo '0 0 * * 0 webadmin /usr/local/bin/tidy_logfiles' > ~/webadmin.cron
scp -p ~/webadmin.cron root@remote_host:/etc/cron.d/webadmin

로컬 webadmin.cron파일을 복사하기 전에 필요에 따라 업데이트하여 여러 번 적용 할 수 있습니다 .

프로비저닝을 제거 할 수도 있습니다.

ssh -q root@remote_host rm -f /etc/cron.d/webadmin

많은 경우 scp/ ssh명령에 루트 암호를 제공 할 수 없습니다 . 대신 공개 / 개인 키 인증서를 설정해야합니다. 또한 로컬 계정 (무엇이든)은 원격 서버에 대한 모든 루트 액세스 권한을 갖습니다. 현재 특정 시나리오에 적합한 지 여부는 확실하지 않습니다.


그것은 내 클라이언트 서버이며 루트로 로그인 할 수 없으며 그들이 나를 죽일 수 있다면 sudo에 로그인 할 수 있습니다. 이것은 webadlmin 작업이므로 webadmin에만 있어야합니다 .sysadmin이 말한 것입니다.
sliders_alpha

@sliders_alpha 작업은 webadmin으로 만 실행됩니다. 루트 동등성을 요구하는 것은 프로비저닝입니다. 그러나 루트가 아닌 솔루션도 찾아 보겠습니다.
roaima

1
+1. /etc/cron.d/패키지 / 배포가 crontab 파일을 여기에 놓을 수 있도록 정확하게이 목적으로 존재합니다.
cas

3

직접 롤링하는 대신 Ansible *을 사용하는 것이 좋습니다. 또는 Puppet 또는 Chef — Ansible은 이와 같은 제로 인프라 배포 스크립트에 적합합니다.

이는 이미 이와 같은 문제를 해결하기위한 모듈이 있기 때문에 구성 관리 도구는 기본 설계 목표로 dem 등성 을 가지고 있기 때문입니다. 이는 실수로 (또는 의도적으로) 다시 실행하더라도 필요할 때만 변경해야하는 특성입니다.

특히 Ansible의 cron 모듈 은 사용자 crontab을 수정할 수 있습니다. 또한 나중에 시스템 크론 탭을 사용하도록 조정하려는 경우 다시 작성하는 것보다 매우 쉽게 조정할 수 있습니다.


* 면책 조항 : 저는 Red Hat에서 일하며 Ansible은 Red Hat이 후원하는 프로젝트입니다.


그렇습니다 .2 개월 전에는 알 수 없었습니다. 이제 대규모 파이썬 배포자 스크립트가 있습니다 (그러나 그는 훌륭하고 읽기 쉽고 유지 관리 가능합니다.)) back is 불가능 (돈 돈 돈)
sliders_alpha

1

대상 계정을 통해 크론 작업을 추가하려면을 실행하십시오 crontab -e. 이 명령은 편집기를 통해 crontab을 전달합니다. crontab을 원하는대로 수정하는 편집기 명령을 사용하도록 지시하십시오. 편집기 명령은 임시 파일 이름이 추가 된 쉘 스 니펫으로 실행됩니다.

unset VISUAL
EDITOR='update_crontab () {
  set -e
  new=$(mktemp)
  if <"$1" grep -v "^#" | grep -w do_stuff; then
    # Remove existing entries containing do_stuff
    grep -v -w do_stuff "$1" >"$new"
  else
    cp "$1" "$new"
  fi
  # Add the new entry
  echo "1 2 3 4 5 do_stuff --new-options" >>"$new"
  mv "$new" "$1"
}
update_crontab' crontab -e

이 방법은 crontab -l | … | crontab -crontab을 동시에 편집 할 경우 경쟁 조건에 취약 하므로이 방법은 기본보다 안정적입니다 . 호출 crontab -l과 호출간에 수정 한 내용은 crontab -취소됩니다.


1

이것은 "지금까지의 최고의 아이디어"코드를 기반으로 @ phillip-zyan-k-lee-stockmann이 제공 한 내용을 수정 한 것 입니다.

그의 (매우 훌륭하고 유용한 스 니펫)의 변경 사항은 기본적으로 다음과 같습니다.

  • 명령 이름뿐만 아니라 시간 문자열을 포함한 전체 항목에 대한 정규식. 그렇게하면 다른 항목에 같은 이름의 명령이나 중복되는 이름의 명령이 있어도 명령 추가를 지원할 수 있습니다. (여전히 동일한 스케줄에 동일한 명령을 두 번 추가하지는 않습니다.)
  • 약간의 로깅
  • 나는 여러 가지 이유로 광산을 매시간으로 바꿨다. crontab 구문에 따라 쉽게 조정할 수 있습니다.

그리고 여기 내가 부르는 것에 대한 코드가 있습니다 crontab-add-hourly.sh.

#!/bin/bash

# PURPOSE:
# To allow simple, programmatic addition of commands/entries into the crontab (if not already present)

cmd=$1
entry="0 * * * * $cmd"
printf "we want to add this entry:\n$entry\n\n" 
escapedEntry=$(printf '%s\n' "$entry" | sed 's:[][\/.^$*]:\\&:g') #from: https://unix.stackexchange.com/a/129063/320236
printf "but first we'll see if it's already in there using this regex pattern:\n$escapedEntry\n\n"

if [[ $(crontab -l | egrep -v '^(#|$)' | grep -q "$escapedEntry"; echo $?) == 1 ]] # from: https://unix.stackexchange.com/a/297377/320236
then
    printf "all clear; pattern was not already present; adding command to crontab hourly:\n$cmd\n\n"
    (crontab -l ; printf "$entry\n\n") | crontab -
else
    printf "pattern already present; no action taken\n\n"
fi

사용법 및 출력 예 :

$ ./crontab-add-hourly.sh my-script.bash

we want to add this entry:
0 * * * * my-script.bash

but first we'll see if it's already in there using this regex pattern:
0 \* \* \* \* my-script\.bash

all clear; pattern was not already present; adding command to crontab hourly:
my-script.bash

0

TL; DR : 실제로 작동하며 Bash 4.4에서 테스트되었습니다.

if [[ $(crontab -l | egrep -v "^(#|$)" | grep -q 'some_command'; echo $?) == 1 ]]
then
    set -f
    printf "$(crontab -l ; echo '* * * * * some_command')\n" | crontab -
    set +f
fi

@Phillip -Zyan K Lee-Stockmann의 의견에 언급 된 것처럼이 솔루션 *은 현재 디렉토리의 모든 파일로 확장 됩니다. 나는 의견의 제안을 얻을 수 없었다. set -f는 와일드 카드 확장을 비활성화합니다 ( https://stackoverflow.com/a/11456496/915441 참조) .

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