Cron'un bir script çalıştırdığı ortamı nasıl simüle edebilirim?


253

Normalde ortamımın kurulumuna sahip olmadığı için cron'un komut dosyalarını nasıl yürüttüğü ile ilgili birkaç problemim var. Bash (?) 'I aynı şekilde cron ile aynı şekilde çağırmanın bir yolu var mı?



@Gregseth'i biraz daha ileri götürerek, bu çözümü verdim: unix.stackexchange.com/questions/27289/…
Robert Brisita

Yanıtlar:


385

Bunu crontab'ınıza ekleyin (geçici olarak):

* * * * * env > ~/cronenv

Çalıştıktan sonra bunu yapın:

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

Bu, cron'unuzun kullanıcının varsayılan kabuğundan bağımsız olarak varsayılan / bin / sh çalıştırdığını varsayar.


5
not: bunu global / etc / crontab dosyasına eklerseniz, kullanıcı adına da ihtiyacınız olacaktır. Örneğin * * * * * root env> ~ / cronenv
Greg

10
İyi, basit bir fikir. Sabırsızlık için '* * * * *' kullanın ve bir sonraki dakika koşun ve oynamayı bitirdiğinizde tekrar kapatmayı unutmayın ;-)
Mads Buus

5
@Madsn Önceki bash kabuğuna geri dönmek için şunu deneyin: exit
spkane

5
Bu cevabın önemi göz ardı edilemez. Bir kitaba paragraf eklenmesi.
Xofo

1
olan env - kedi ~ / cronenv` / bin / sh` da cron işi olarak yazılmalıdır? lütfen bir örnek verin
JavaSa

61

Cron varsayılan olarak yalnızca bu ortamı sağlar:

  • HOME kullanıcının ana dizini
  • LOGNAME kullanıcı girişi
  • PATH=/usr/bin:/usr/sbin
  • SHELL=/usr/bin/sh

Daha fazlasına ihtiyacınız varsa, crontab'daki zamanlama tablosundan önce ortamınızı tanımladığınız bir komut dosyasını kaynaklayabilirsiniz.


7
.genellikle güvenlik nedeniylePATH artık bir parçası değildir .
l0b0

49

Birkaç yaklaşım:

  1. Cron env'yi dışa aktarın ve kaynaklayın:

    Ekle

    * * * * * env > ~/cronenv

    crontab'ınıza, bir kez çalışmasına izin verin, geri kapatın, sonra çalıştırın

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

    Ve şimdi shcron ortamına sahip bir oturumun içindesiniz

  2. Ortamınızı cron'a getirin

    Yukarıdaki egzersizi atlayabilir ve . ~/.profilecron işinizin önünde bir

    * * * * * . ~/.profile; your_command
  3. Ekranı kullan

    Yukarıdaki iki çözüm, çalışan bir X oturumuna bağlı, dbusvb. Erişimi olan bir ortam sağlamaları nedeniyle başarısız olur. Örneğin, Ubuntu'da nmcli(Ağ Yöneticisi) yukarıdaki iki yaklaşımda çalışır, ancak yine de cronda başarısız olur.

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

    Yukarıdaki satırı cron'a ekleyin, bir kez çalışmasına izin verin, tekrar kapatın. Ekran oturumunuza bağlanın (ekran -r). Eğer ekran oturumu denetliyorsanız (ile oluşturuldu psonlar başkentlerinde bazen (örn olduğunu unutmayın) ps | grep SCREEN)

    Şimdi bile nmclive benzerleri başarısız olacak.


22

Koşabilirsin:

env - your_command arguments

Bu, komutunuzu boş bir ortamla çalıştıracaktır.


4
cron tamamen boş bir ortamda çalışmaz, değil mi?
jldupont

2
gregseth, çevreye dahil edilen değişkenleri cron ile tanımladı. Bu değişkenleri komut satırına dahil edebilirsiniz. $ env - PATH = "$ PATH" komut bağımsız
değişkenleri

4
@DragonFax @dimba Hile yapıyor env - HOME="$HOME" LOGNAME="$USER" PATH="/usr/bin:/bin" SHELL="$(which sh)" command argumentsgibi görünüyor
l0b0

Bu, "düşmanca" veya bilinmeyen ortamlardaki komut dosyalarını test etmek için harika bir basit yöntemdir. Eğer bunun içinde çalışacak kadar açıksanız, cron altında çalışacaktır.
Oli


13

Altı yıl sonra cevap: çevre uyuşmazlığı sorunu, systemd“zamanlayıcılar” ın bir cron değişimi olarak çözdüğü sorunlardan biridir . Systemd "hizmetini" CLI'den veya cron üzerinden çalıştırsanız da, ortam uyumsuzluğu sorununu önleyerek tam olarak aynı ortamı alır.

Cron işlerinin el ile geçtiklerinde başarısız olmasına neden olan en yaygın sorun, cron $PATHtarafından ayarlanan kısıtlayıcı varsayılan değerdir; bu Ubuntu 16.04'te:

"/usr/bin:/bin"

Bunun aksine, Ubuntu 16.04'te varsayılan $PATHayar systemd:

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

Bu nedenle, bir systemd zamanlayıcısının daha fazla güçlük çekmeden bir ikili bulması için daha iyi bir şans var.

Systemd zamanlayıcıları ile dezavantaj, onları kurmak için biraz daha zaman var. Önce, çalıştırmak istediğiniz programı tanımlamak için bir "hizmet" dosyası ve üzerinde çalışacak programı tanımlamak için bir "zamanlayıcı" dosyası ve son olarak etkinleştirmek için zamanlayıcıyı "etkinleştirin".


10

Env çalıştıran ve stdout'u bir dosyaya yönlendiren bir cron işi oluşturun. Bir cron işi ile aynı ortamı oluşturmak için dosyayı "env -" ile birlikte kullanın.


Üzgünüm bu beni şaşırttı. "env - script" yeterli değil mi?
Jorge Vargas

Bu size boş bir ortam sağlayacaktır. Komut dosyalarını cron üzerinden çalıştırdığınızda ortam boş değildir.
Jens Carlberg


2

Varsayılan olarak, cronsisteminizin fikri ne olursa olsun işlerini yürütür sh. Bu, gerçek Bourne kabuğu olabilir ya da olabilir dash, ash, kshya da bash(ya da başka bir) sembolik olarak sh(ve POSIX modunda çalışan bir sonucu olarak).

Yapılacak en iyi şey, komut dosyalarınızın ihtiyaç duyduklarına sahip olduğundan emin olmak ve onlar için hiçbir şey sağlanmadığını varsaymaktır. Bu nedenle, tam dizin belirtimlerini kullanmalı ve $PATHkendiniz gibi ortam değişkenlerini ayarlamalısınız .


Tam olarak çözmeye çalıştığım şey bu. Yanlışlıkla bir şey olduğunu bilen tonlarca sorunla karşılaşırız. Tam yollar yapmak ve env değişkenlerini ayarlamak ve tüm önemsiz korkunç korkunç devasa cron çizgileriyle sonuçlanıyor
Jorge Vargas

re * sh üzgünüm bash = shell ile büyüdüm, bu yüzden alternatifleri (ve bazen daha iyi) kabukları hatırlamak benim için zor.
Jorge Vargas

1
@Jorge: crontab'daki satırlar oldukça kısa olmalıdır. Komut dosyasında (veya bir sarıcı komut dosyasında) ihtiyacınız olan tüm ayarları yapmanız gerekir. Örnek olarak bir crontab'dan tipik bir satır: 0 0 * * 1 /path/to/executable >/dev/null 2>&1ve sonra, "yürütülebilir" içinde $PATH, vb. İçin değerler ayarlayabilir ve giriş ve çıkış dosyaları, vb. İçin tam dizin özellikleri kullanırdım. Örneğin:/path/to/do_something /another/path/input_file /another/path/to/output_file
sonraki duyuruya kadar duraklatıldı.

1

Bulduğum bir başka basit yol (ancak hataya eğilimli olabilir, hala test ediyorum), komutunuzdan önce kullanıcının profil dosyalarını kaynaklamaktır.

/Etc/cron.d/ betiğinin düzenlenmesi:

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

Şuna dönüşür:

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

Kirli, ama benim için işi halletti. Bir girişi simüle etmenin bir yolu var mı? Sadece çalıştırabileceğin bir komut mu?bash --loginişe yaramadı. Yine de gitmenin daha iyi bir yolu gibi görünüyor.

EDIT: Bu sağlam bir çözüm gibi görünüyor: 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

Kabul edilen cevap, cron'un kullanacağı ortamla bir komut dosyası çalıştırmak için bir yol sağlar. Diğerlerinin de belirttiği gibi, bu cron işlerinde hata ayıklamak için gerekli olan tek kriter değildir.

Gerçekten de, cron ayrıca, bağlı bir giriş, vb. Olmadan etkileşimli olmayan bir terminal kullanır.

Bu yardımcı olursa, cron tarafından çalıştırılacağı gibi ağrısız bir komut / komut dosyası çalışmasını sağlayan bir komut dosyası yazdım. Komut / komut dosyanızla ilk argüman olarak çağırın ve iyisiniz.

Bu komut dosyası Github'da da barındırılıyor (ve muhtemelen güncelleniyor) .

#!/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

Yanıt https://stackoverflow.com/a/2546509/5593430 , cron ortamının nasıl elde edileceğini ve komut dosyanız için nasıl kullanılacağını gösterir. Ancak ortamın, kullandığınız crontab dosyasına bağlı olarak değişebileceğini unutmayın. Ortamı kurtarmak için üç farklı cron girişi oluşturdum env > log. Bunlar bir Amazon Linux 4.4.35-33.55.amzn1.x86_64 sonuçlarıdır.

1. Global / vb / root kullanıcısı ile 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. root ( crontab -e) kullanıcı crontab'ı

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/ içindeki komut dosyası

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

En önemlisi PATH, PWDve HOMEfarklıdır. Kararlı bir ortama güvenmek için bunları cron komut dosyalarınızda ayarladığınızdan emin olun.


-8

Olduğuna inanmıyorum; bir cron işini test etmenin tek yolu, onu bir veya iki dakika içinde çalıştırmak ve sonra beklemek.


Bu yüzden simüle istiyorum
Jorge Vargas
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.