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ı?
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ı?
Yanıtlar:
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.
env -
kedi ~ / cronenv` / bin / sh` da cron işi olarak yazılmalıdır? lütfen bir örnek verin
Cron varsayılan olarak yalnızca bu ortamı sağlar:
HOME
kullanıcının ana diziniLOGNAME
kullanıcı girişiPATH=/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.
Birkaç yaklaşım:
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 sh
cron ortamına sahip bir oturumun içindesiniz
Ortamınızı cron'a getirin
Yukarıdaki egzersizi atlayabilir ve . ~/.profile
cron işinizin önünde bir
* * * * * . ~/.profile; your_command
Ekranı kullan
Yukarıdaki iki çözüm, çalışan bir X oturumuna bağlı, dbus
vb. 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 ps
onlar başkentlerinde bazen (örn olduğunu unutmayın) ps | grep SCREEN
)
Şimdi bile nmcli
ve benzerleri başarısız olacak.
Koşabilirsin:
env - your_command arguments
Bu, komutunuzu boş bir ortamla çalıştıracaktır.
env - HOME="$HOME" LOGNAME="$USER" PATH="/usr/bin:/bin" SHELL="$(which sh)" command arguments
gibi görünüyor
Hesabın kabuğuna bağlı olarak
sudo su
env -i /bin/sh
veya
sudo su
env -i /bin/bash --noprofile --norc
Gönderen http://matthew.mceachen.us/blog/howto-simulate-the-cron-environment-1018.html
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 $PATH
tarafı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 $PATH
ayar 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".
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.
Unutmayın, cron'un üst öğesi başlatıldığından programları kontrol terminali olmadan çalıştırır. Bunu aşağıdaki gibi bir araçla simüle edebilirsiniz:
Varsayılan olarak, cron
sisteminizin fikri ne olursa olsun işlerini yürütür sh
. Bu, gerçek Bourne kabuğu olabilir ya da olabilir dash
, ash
, ksh
ya 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 $PATH
kendiniz gibi ortam değişkenlerini ayarlamalısınız .
0 0 * * 1 /path/to/executable >/dev/null 2>&1
ve 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
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 --login
iş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
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"
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.
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
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
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
, PWD
ve HOME
farklıdır. Kararlı bir ortama güvenmek için bunları cron komut dosyalarınızda ayarladığınızdan emin olun.
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.