Programlı olarak crontab'a bir şeyler ekleyin (ssh üzeri)


13

Bir dağıtım komut dosyası var, bir kullanıcıya bir şey eklemek gerekir crontab(her XXX günde bir günlükleri temizleyen bir komut dosyası tetiklemek), ancak bu yalnızca ilk dağıtım sırasında veya güncelleştirilmesi gerektiğinde yapılmalıdır.

(Koşabilirim xxx.py deploy envveya xxx.py update env)

bu yüzden bunu yapmak zorunda:

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

Dosyayı crontabkullanmadan crontab -eveya düzenlemeden bir şeyi nasıl ekleyeceğinizi / kontrol edeceğim / kaldıracağımı göremiyorum crontab(indirin, yeniden yazın, yeniden yükleyin)

PS: bu kullanıcıya özgü bir cronjob, "webadmin" yapacak ve bunu yapmak için sudo kullanmamalıdır.


1
Kullanıcıya özel bir crontab içinde olması gerekir mi? Hazır ambalajlı çoğu cron işi /etc/cron.* dizinlerinden birine girer.
CVn

CentOS'da var /etc/cron.dmı? Öyleyse, komut dosyanızı uygulamanıza özgü bir ad kullanarak oraya koyun
roaima

evet kullanıcıya özgüdür. /Etc/cron.d dosyasına ekleyemiyorum, çünkü bu bir kök dosyası, bu yüzden sadece kökün işi içeride alowed (sudo yapabilirim ama bana söylenen kötü bir uygulama)
sliders_alpha

1
Aynı şekilde /etc/crontab, dosyalar /etc/cron.d/hemen zamanlama spec sonra, kullanıcı adı için ek bir alan var. örn * * * * * username /path/to/script. Bkz man 5 crontabve aramak SYSTEM CRON.
cas

Yanıtlar:


15

şimdiye kadarki en iyi fikrim

önce içeriğin orada olması gerekenlerle eşleşip eşleşmediğini kontrol etmek ve yalnızca aşağıdakileri içermiyorsa güncellemek için:

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

ancak bu, o cron görevi etrafında ayrı bir komut dosyası oluşturacak kadar karmaşık hale gelir.

diğer fikirler

dizeyi crontab'a stdin ile gönderebilirsiniz (dikkat edin, bu önceki crontab girişlerini temizler):

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

bu bile ssh ile çalışmalıdır:

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

dosyaya eklemek istiyorsanız bunu kullanabilirsiniz:

# 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 -"

bu bağlıdır: orada ne olurdu ihtiyacınız var? :)
Phillip -Zyan K Lee- Stockmann

awww ... kök olarak çalışmıyor mu? ...
Yeniden

Bunu beğendim: D
sliders_alpha

Bu çözümle ilgili iki sorunum vardı: 1) bir dosya listesine echo '*...genişletildi *. 2) crontab'daki satır sonları silindi.
Heath Raftery

Bu sorunları şu şekilde çözebildim: 1) değişiklik echo "*...ve 2) echo $satırın başından kaldır .
Heath Raftery

3

Kayıt için kullanmanızı önereceğim /etc/cron.d/. Buraya yalnızca root dosyaları yazabilir, ancak girişler herhangi bir kullanıcı olarak çalıştırılabilir (gerek kalmadan sudo).

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

Bu, yerel webadmin.crondosyayı kopyalamadan önce gerektiği gibi güncelleyerek birden çok kez uygulanabilir .

Hazırlığı bile kaldırabilirsiniz:

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

Çoğu durumda scp/ sshkomutları için root şifresi sağlayamayacağınızı unutmayın . Bunun yerine genel / özel anahtar sertifikaları ayarlamanız gerekir. Ayrıca, ima yoluyla, yerel hesap (ne olursa olsun) uzak sunucuya tam kök erişimine sahip olacaktır. Şu anda bu özel senaryo için gösteri-durdurucu olup olmayacağı belli değil.


Bu benim istemci sunucum, root olarak giriş yapamıyorum, içine girebiliyorum AMA, eğer yaparsam beni öldürürler. Bu bir webadlmin işi, bu yüzden sadece webadmin işlerinde olmalı, sysadmin bana böyle söyledi.
sliders_alpha

@sliders_alpha iş yalnızca web yöneticisi olarak çalışır. Kök eşdeğerini gerektiren koşul budur. Ancak, kök olmayan bir çözüm de arayacağım.
roaima

1
+1. /etc/cron.d/tam olarak bu amaç için var - böylece paketler / dağıtımlar bir crontab dosyasını buraya bırakabilir.
cas

3

Kendi için haddeleme yerine Ansible * kullanmanızı tavsiye ederim. Ya da Kukla veya Şef - ancak Ansible, bu tür sıfır altyapı dağıtım komut dosyaları için çok uygundur.

Bunun nedeni, bu tür sorunları çözmek için zaten modüller olması ve yapılandırma yönetim araçlarının temel bir tasarım hedefi olarak idempotence olmasıdır - bu, yalnızca yanlışlıkla (veya kasıtlı olarak) tekrar çalıştırsanız bile değişmesi gereken özelliktir.

Özellikle, Ansible'ın cron modülü kullanıcı crontablarını değiştirebilir. Bonus olarak, daha sonra sistem crontab'larını kullanacak şekilde ayarlamak isterseniz, yeniden yazmaktan ziyade çok kolay bir ayar olacaktır.


* Feragatname: Red Hat için çalışıyorum ve Ansible Red Hat sponsorluğunda bir projedir.


Evet, bir şey, 2 ay önce ansible hakkında bir şey bilmiyordum ve şimdi büyük bir python konuşmacı komut dosyamız var (ama o MUHTEŞEM, okunabilir, bakım yapılabilir;)) Bir dahaki sefere, ansible kullanacağım ama şu anda devam edeceğim back is imkansız (para para para)
sliders_alpha

1

Hedef hesap üzerinden bir cron işi eklemek istiyorsanız, çalıştırın crontab -e. Bu komut crontab'ı bir editör aracılığıyla geçirir. Crontab'ı istediğiniz gibi değiştiren bir editör komutu kullanmasını söyleyin. Editör komutu, geçici bir dosyanın adının eklendiği bir kabuk snippet'i olarak yürütülür.

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

Bu yaklaşım, yerelden daha güvenilirdir crontab -l | … | crontab -çünkü crontab aynı anda düzenlenirse bu bir yarış koşullarına karşı savunmasızdır: çağrı crontab -lve çağrı arasında yapılan değişiklikler crontab -geri alınacaktır.


1

Bu, "Şimdiye kadarki en iyi fikir" koduna dayanarak @ phillip-zyan-k-lee-stockmann'ın sunduklarının bir uyarlamasıdır .

Onun (mükemmel ve yararlı snippet'ten) yaptığım değişiklikler temel olarak:

  • Yalnızca komut adı için değil, zaman dizeleri dahil tüm giriş için normal ifade. Bu şekilde, diğer girişlerde aynı adlı veya çakışan adlı komutlar olsa bile bir komut eklemeyi destekleyebilir. (Yine de aynı komutu aynı programa iki kez eklemez.)
  • Biraz günlüğe kaydetme
  • Çeşitli nedenlerle madeni saatlik olarak değiştirdim (ve adlandırdım); crontab sözdizimi başına kolayca ayarlanabilir

Ve işte benim aradığım kod 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

Örnek kullanım ve çıktı:

$ ./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: Bu gerçekten işe yarıyor, Bash 4.4'te test edildi.

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 yanıtının yorumlarında belirtildiği gibi, bu çözüm *geçerli dizindeki tüm dosyalara genişler . Yorum önerilerinin işe yaramasını sağlayamadım. set -f joker karakter genişletmeyi devre dışı bırakır, bkz. https://stackoverflow.com/a/11456496/915441 .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.