Jak symulować środowisko, z którym cron wykonuje skrypt?
253
Zwykle mam kilka problemów z tym, jak cron wykonuje skrypty, ponieważ normalnie nie mają konfiguracji mojego środowiska. Czy istnieje sposób na wywołanie bash (?) W taki sam sposób, jak robi to cron, aby móc przetestować skrypty przed ich zainstalowaniem?
na swoim crontabie, pozwól mu raz uruchomić, wyłącz go z powrotem, a następnie biegnij
env -`cat ~/cronenv`/bin/sh
Jesteś teraz w shsesji ze środowiskiem crona
Doprowadź swoje środowisko do crona
Możesz pominąć ćwiczenie i po prostu zrobić . ~/.profileprzed swoją pracą crona, np
*****.~/.profile; your_command
Użyj ekranu
Powyższe dwa rozwiązania wciąż zawodzą, ponieważ zapewniają środowisko połączone z działającą sesją X, z dostępem do dbusitp. Na przykład w Ubuntu nmcli(Network Manager) będzie działał w dwóch powyższych podejściach, ale nadal zawiedzie w cron.
*****/usr/bin/screen -dm
Dodaj powyższą linię do crona, pozwól jej uruchomić się raz, wyłącz go z powrotem. Połącz się z sesją ekranową (screen -r). Jeśli sprawdzasz, czy sesja ekranowa została utworzona (z ps), pamiętaj, że czasami są wielkimi literami (np. ps | grep SCREEN)
Jest to świetna prosta metoda testowania skryptów w „wrogim” lub nieznanym środowisku. Jeśli masz wystarczającą jasność, że będzie w tym działać, będzie działał pod cronem.
Odpowiedź sześć lat później: problem niedopasowania środowiska jest jednym z problemów rozwiązanych przez systemd„timery” jako zamiennik crona. Niezależnie od tego, czy uruchamiasz systemową „usługę” z interfejsu CLI, czy za pośrednictwem crona, otrzymuje on dokładnie to samo środowisko, unikając problemu niedopasowania środowiska.
Najczęstszym problemem powodującym niepowodzenie zadań cron po ich ręcznym przekazaniu jest restrykcyjne ustawienie domyślne $PATHustawione przez crona, takie jak w Ubuntu 16.04:
"/usr/bin:/bin"
Natomiast domyślnym $PATHustawieniem systemddla Ubuntu 16.04 jest:
Jest więc już większa szansa, że systemowy licznik znajdzie plik binarny bez dalszych kłopotów.
Wadą systemowych timerów jest nieco więcej czasu na ich konfigurację. Najpierw tworzysz plik „usługi”, aby zdefiniować, co chcesz uruchomić, i plik „timera”, aby zdefiniować harmonogram uruchamiania, a na koniec „włączyć” timer, aby go aktywować.
Utwórz zadanie cron, które uruchamia env i przekierowuje standardowe wyjście do pliku. Użyj pliku obok „env -”, aby stworzyć to samo środowisko co zadanie cron.
Nie zapominaj, że ponieważ rodzicem crona jest init, uruchamia on programy bez terminala sterującego. Możesz to zasymulować za pomocą takiego narzędzia:
Domyślnie cronwykonuje zadania przy użyciu dowolnego pomysłu systemu sh. To może być rzeczywiste lub powłoki Bourne dash, ash, kshi bash(lub inny) dowiązane do sh(i w rezultacie działa w trybie POSIX).
Najlepiej jest upewnić się, że skrypty mają to, czego potrzebują, i założyć, że nic dla nich nie ma. Dlatego powinieneś używać pełnych specyfikacji katalogu i ustawiać zmienne środowiskowe, takie jak $PATHty.
Właśnie to próbuję rozwiązać. Mamy mnóstwo problemów ze skryptami, które zakładają coś przez pomyłkę. Robienie pełnych ścieżek i ustawianie zmiennych env i wszystkie śmieci kończą się straszliwymi, ogromnymi, niemożliwymi do utrzymania liniami cron
@Jorge: wiersze w crontab powinny być dość krótkie. Powinieneś wykonać wszystkie potrzebne ustawienia w skrypcie (lub skrypcie opakowania). Oto typowy wiersz z pliku crontab jako przykład: 0 0 * * 1 /path/to/executable >/dev/null 2>&1a następnie w „wykonywalnym” ustawiłbym wartości dla $PATHitd. I użyłem pełnych specyfikacji katalogów do plików wejściowych i wyjściowych itp. Na przykład:/path/to/do_something /another/path/input_file /another/path/to/output_file
Brudny, ale wykonał dla mnie robotę. Czy istnieje sposób na symulację logowania? Tylko polecenie, które możesz uruchomić? bash --loginnie działało Wygląda na to, że byłby to jednak lepszy sposób.
Zaakceptowana odpowiedź umożliwia uruchomienie skryptu w środowisku, którego używa cron. Jak zauważyli inni, nie jest to jedyne potrzebne kryterium do debugowania zadań cron.
Rzeczywiście, cron używa również nieinteraktywnego terminala, bez dołączonego wejścia itp.
Jeśli to pomoże, napisałem skrypt, który umożliwia bezbolesne uruchomienie polecenia / skryptu, tak jakby był uruchamiany przez crona. Wywołaj go za pomocą polecenia / skryptu jako pierwszego argumentu i jesteś dobry.
Ten skrypt jest również hostowany (i prawdopodobnie aktualizowany) w Github .
#!/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 shellfunction 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 0fiif[ $(whoami)!="root"];then
echo "Only root is supported at the moment"
exit 1fi# 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 0fi# 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"
Odpowiedź https://stackoverflow.com/a/2546509/5593430 pokazuje, jak uzyskać środowisko cron i używać go w skrypcie. Należy jednak pamiętać, że środowisko może się różnić w zależności od używanego pliku crontab. Utworzyłem trzy różne wpisy cron, aby za pomocą zapisać środowisko env > log. Są to wyniki w Amazon Linux 4.4.35-33.55.amzn1.x86_64.
Nie wierzę w to; jedynym sposobem, w jaki wiem, aby przetestować zadanie crona, jest skonfigurowanie go do uruchomienia za minutę lub dwie w przyszłości, a następnie czekania.
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.