プログラムで(sshを介して)何かをcrontabに追加する


13

私は導入スクリプトを持っています。ユーザーに何かを追加する必要がありますcrontab(XXX日ごとにログをクリーンアップするスクリプトをトリガーします)。

(私は実行することができますxxx.py deploy envxxx.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(ダウンロード、再書き込み、再アップロード)

PS:これはユーザー固有のcronjobであり、 "webadmin"が実行する予定であり、sudoを使用して実行するべきではありません。


1
ユーザー固有のcrontabにある必要がありますか?ほとんどの事前にパッケージ化されたcronジョブは、/ etc / cron。*ディレクトリの1つに移動します。
CVn

CentOSにはあり/etc/cron.dますか?その場合は、アプリケーションに固有の名前を使用してスクリプトをそこに
挿入し

はい、それはユーザー固有です。/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 2016

awww ...ルートとして実行されていませんか?...書き直します...
Phillip -Zyan K Lee- Stockmann

ええ、私はそれが好きです:D
sliders_alpha

このソリューションには2つの問題がありました。1)をファイルのリストにecho '*...拡張し*ました。2)crontabの行末が削除されました。
ヒースラフター

私はこれらの問題を次の方法で修正できました:1)に変更しecho "*...、2)echo $行の先頭から削除します。
ヒースラフター

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コマンドにrootのパスワードを提供できないことに注意してください。代わりに、公開鍵/秘密鍵証明書をセットアップする必要があります。また、暗黙的にローカルアカウント(それが何であれ)は、リモートサーバーへの完全なrootアクセス権を持ちます。それがあなたの特定のシナリオのショーストッパーになるかどうかは現時点では不明です。


これは私のクライアントサーバーです。rootとしてログインすることはできませんが、sudoを実行することはできますが、そうすると、彼らは私を殺します。これはwebadlminの仕事なので、webadminのものだけにすべきであり、それはsysadminが私に言ったことです。
Sliders_alpha 2016

@sliders_alphaジョブはwebadminとしてのみ実行されます。ルートの同等性を必要とするのはプロビジョニングです。ただし、ルート以外の解決策も探します。
roaima

1
+1。/etc/cron.d/まさにこの目的のために存在します-そのため、パッケージ/デプロイメントはここにcrontabファイルをドロップすることができます。
cas

3

自分でロールするのではなく、Ansible *を使用することを強くお勧めします。またはPuppetまたはChef —しかし、Ansibleは、このようなインフラストラクチャなしのデプロイスクリプトに適しています。

これは、このような問題を解決するためのモジュールがすでにあり、構成管理ツールが基本的な設計目標としてべき等性を持っているためです。これは、誤って(または意図的に)再度実行した場合でも、必要なときにのみ変更できるという特性です。

特に、Ansibleのcronモジュールはユーザーのcrontabを変更できます。おまけとして、後でシステムのcrontabを使用するように調整したい場合は、書き換えるのではなく、非常に簡単に調整できます。


*免責事項:私はRed Hatで働いており、AnsibleはRed Hatがスポンサーとなっているプロジェクトです。


うん、実のところ、私は2か月前にansibleを知りませんでした、そして今、大規模なpythonデプロイヤースクリプトがあります(しかし、彼は素晴らしい、読みやすく、メンテナンス可能です;))次回は、ansibleを使用しますが、今すぐ戻ることは不可能です(お金のお金とお金)
Sliders_alpha

1

ターゲットアカウントを介してcronジョブを追加する場合は、を実行し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のが同時に編集された場合、この1は、競合状態に対して脆弱であるため、crontab -lとの呼び出しcrontab -元に戻すだろう。


1

これは、@ phillip-zyan-k-lee-stockmannが提供した、「これまでのところ最高のアイデア」のコードに基づいたものです。

彼の(優れた役立つスニペット)からの私の変更は、基本的には次のとおりです。

  • コマンド名だけでなく、時間文字列を含むエントリ全体の正規表現。これにより、他のエントリに同じ名前のコマンドまたは重複する名前のコマンドがある場合でも、コマンドの追加をサポートできます。(同じコマンドを同じスケジュールで2回追加することはありません。)
  • 少しロギング
  • 私はさまざまな理由で鉱山を時間単位に切り替えました(そして名前を付けました)。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.