Jak uruchomić polecenie cron z istniejącymi zmiennymi środowiskowymi?

114

Jak uruchomić polecenie cron z istniejącymi zmiennymi środowiskowymi?

Jeśli pojawi się monit powłoki, mogę wpisać echo $ORACLE_HOMEi uzyskać ścieżkę. Jest to jedna z moich zmiennych środowiskowych, które są ustawione w mojej ~/.profile. Jednak wydaje się, że ~/.profilenie zostanie załadowane skrypty Fron crona i tak moje skrypty nie dlatego, że $ORACLE_HOMEzmienna nie jest ustawiona.

W tym pytaniu autor wspomina o utworzeniu ~/.cronfileprofilu, który konfiguruje zmienne dla crona, a następnie dokonuje obejścia, aby załadować wszystkie swoje polecenia crona do skryptów, które przechowuje w swoim ~/Cronkatalogu. Plik taki ~/.cronfilewydaje się dobrym pomysłem, ale reszta odpowiedzi wydaje się trochę kłopotliwa i miałem nadzieję, że ktoś powie mi łatwiejszy sposób na uzyskanie tego samego rezultatu.

Przypuszczam, że na początku moich skryptów mógłbym dodać coś takiego, source ~/.profileale wydaje się, że może to być zbędne.

Więc jak mogę zmusić moje skrypty cron do ładowania zmiennych z mojego profilu powłoki interaktywnej?

cwd
źródło
Jak dodawanie source ~/.profiledo programu jest zbędne? Programy dziedziczą swoje środowisko po programie wywołującym. Jeśli ten program wywołujący nie jest twoją powłoką, to w jaki sposób program dekadujący uzyska pożądane środowisko?
Arcege
Tutaj już napisałem swoją odpowiedź na podobne pytanie . Po prostu używa su -ldo skonfigurowania normalnego środowiska logowania, w tym $ PATH dla użytkownika root lub innego konkretnego użytkownika.
tasket

Odpowiedzi:

141

W crontab, zanim wydasz polecenie, dodaj . $HOME/.profile. Na przykład:

0 5 * * * . $HOME/.profile; /path/to/command/to/run

Cronnic nie wie o twojej skorupie; jest uruchamiany przez system, więc ma minimalne środowisko. Jeśli chcesz czegoś, musisz mieć to przy sobie.

Arcege
źródło
14
Co robi .przed skryptem? (nie jestem pewien, jak bym to zrobił man). Dlaczego to się różni source?
cwd
25
.Komenda jest oryginalny polecenie source. Są one równoważne w powłoce i nieco łatwiejsze do pisania, szczególnie w crontab. Aby uzyskać więcej informacji, wpisz help .lub wyszukaj na ^SHELL BUILTIN COMMANDSstronie podręcznika dla bashlub na górze man zshbuiltins . Running wpisz .` powie ci, że polecenie jest wbudowane.
Arcege
9
W zależności od dystrybucji Linuksa, być może trzeba zmienić .profileprzez .bash_profile. Sprawdź, który .profileplik istnieje w katalogu osobistym użytkownika.
Frosty Z
@Arcege To nie działa dla mnie (Fedora Core 21), i przypuszczam, że to dlatego, że poziom powłoki spada z powrotem. Zamiast tego, DZIAŁA to, jeśli je pozyskasz.
Richard T
3
Jest prawdopodobne, że jeśli to nie działa, to dlatego, że SHELL dla skryptu cron nie jest ustawiony na bash, więc nie działa tak, jak można się spodziewać.
Daniel Farrell,
40

Inną opcją, która jest dla mnie łatwiejsza, jest uruchomienie skryptu z cronem i włączenie środowiska w skrypcie.

W pliku crontab -e:

SHELL=/bin/bash

*/1 * * * * $HOME/cron_job.sh

W pliku cron_job.sh:

#!/bin/bash
source $HOME/.bash_profile
some_other_cmd

Każde polecenie po źródle pliku .bash_profile będzie miało środowisko tak, jakbyś się zalogował.

Robert Brisita
źródło
5
Kiedy działałem na AWS Linux AMI, nawet nie przyszło mi do głowy, że cron nie użyje go /bin/bashjako powłoki. Ciągle zastanawiałem się, dlaczego takie rzeczy cd /path/to/project; source .varsdziałałyby, gdy File not foundwpisałem je ręcznie, ale zawiodły ( ), gdy zostały włączone do cronjob. Kluczową linią dla mnie było ustawienie SHELL=/bin/bashtak, że mogłem używać znanych komend bash w każdym cronjobu. /bin/sh/(najwyraźniej domyślna powłoka crona) jest bardzo ograniczająca.
Hartley Brody,
Szkoda, że ​​nie można określić plików środowiska na górze crona, tak jak można określić indywidualne zmienne środowiskowe. Systemd ma EnvironmentFilejednostkę serwisową. Szkoda, że ​​cron nie ma czegoś podobnego.
radtek
zmuszaj wszystkie skrypty do używania / bin / bash we wszystkich plikach crontab, co nie jest dobrym pomysłem, a także co jest z linią cron: * / 1 * * * * $ HOME / cron_job.sh… * / 1 jest dobre dla CO ?!? jedna gwiazdka oznacza, że ​​będzie wykonywana co minutę / 1 oznacza, że ​​będzie wykonywana co minutę, jako odpowiedź w sprytnej społeczności jest to paskudny grzech, teraz uważam, że jesteś bardzo zdezorientowany, mówiąc najlepiej… przepraszam
THESorcerer
1
To się nazywa przykład. Dostosuj się do swoich potrzeb lub nie używaj go wcale. Różne pociągnięcia dla różnych ludzi.
Robert Brisita,
4
Jeśli $SHELLtak /bin/sh, sourcepolecenie nie istnieje. Użyj .zamiast tego.
Melle
18

Inną opcją, którą uważam za łatwiejszą, jest uruchomienie skryptu za pomocą crona i nakazanie bashowi zalogowania się (stąd użycie /etc/profile.d/...definicji środowiska)

W crontab -epliku:

*/1 * * * * bash -l -c './cron_job.sh'
*/1 * * * * bash -l -c 'php -f ./cron_job.php'

Każde polecenie po źródle .bash_profilebędzie miało środowisko tak, jakbyś się zalogował.

Artistan
źródło
10

Zły pomysł. Ogólna praktyka polega na konkretnym ustawianiu wszystkich wymaganych zmiennych środowiskowych w skrypcie, który ma być uruchamiany z zadania cron.

fpmurphy
źródło
Zgadzam się z @fpmurphy, że w ten sposób zapewnia również bezpieczne środowisko procesowe. Jeśli chcesz ustawić tylko kilka zmiennych z crona, możesz użyć /usr/bin/envpolecenia, aby ustawić zmienne, a następnie może działać jako proces środowiskowy dla cronjob.
Nikhil Mulley,
envdirprzychodzi na myśl również Daemontools .
sr_
6
Jestem za bezpieczeństwem, ale być może uda mi się utworzyć plik ~/.cronvarsi dołączyć go do profilu, a także do moich skryptów cron. Nie chcę na stałe kodować zmiennych środowiskowych w każdym ze skryptów, które uruchamiam, ponieważ kiedy ścieżki zmieniają się na stałe, ścieżki w każdym pliku nie są łatwe do utrzymania. Wygląda na to, że pozwoliłoby na scentralizowane miejsce na potrzebne zmienne i nadal zapobiegałoby ładowaniu innych zmiennych.
cwd 21.12.11
4

Ta składnia zdecydowanie ci pomaga. Nie rozumiem składni, ale działa. Oracle używa tej składni podczas wdrażania Oracle Configuration Manager do crontab, dlatego uważam, że jest to właściwe rozwiązanie.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters
meir
źródło
2

Niedawno natknąłem się na przypadek, w którym musiałem wykonać ogólny cronjob jako root, ale jednocześnie musiałem wykonać podkomendę jako inny użytkownik (co wymagało pozyskania środowiska tego użytkownika). Wybrałem następujące podejście:

# m  h  dom  mon  dow  user  command
*/5  *   *    *    *   root  (sudo -i -u <the user> command-to-be-run-as-user) && command-to-be-run-as-root

Kluczową częścią jest -iprzekazywany argument , sudoktóry wykona dane polecenie w osobnej powłoce logowania (co z kolei oznacza, że ​​pliki dot użytkownika zostaną pozyskane).

PS: Zauważ, że userkolumna jest dostępna tylko /etc/crontabi /etc/cron.d/*plików.

balu
źródło
1

Rozwiązanie, które dla mnie zadziałało, zostało opisane tutaj .

Tworzysz skrypt otoki, który wywołuje . ~/.cronfile, a następnie robi to, co chcesz. Ten skrypt jest uruchamiany przez crona.

W ~/.cronfileokreślasz środowisko dla twoich zadań cron.

weekendy
źródło
1

Tak, możesz użyć „dobrze znanych obejść” (z których kilka zostało wymienionych). Jest to kolejny sposób na powiedzenie, że wszyscy wiedzą, że jest to bzdura, chociaż niektórzy będą nazywać to „zabezpieczeniem”, ponieważ wydali co najmniej tyle samo potknięć o tę porażkę (ure), co ty, i chcieliby pomyśleć, że ich zmarnowany czas nie był niczym. Jest to odpowiednik cron klawiatury QWERTY.

Podejrzewam, że pierwotnym powodem mogła być wydajność, tak że skrypty uruchamiane raz na minutę nie spędzałyby czasu na czytaniu skryptów rc. Pierwotnie cron nie był tak naprawdę w ogóle konfigurowalny, więc domyślnie była naprawdę jedyną opcją.

Nie ma dodatkowego bezpieczeństwa, ponieważ nie ma prostej konfiguracji lub metody, aby cron po prostu przejął środowisko interaktywnej powłoki zamiast użytkowników wykonujących głupią gimnastykę. Na nowoczesnej maszynie generalnie nie ma zauważalnego wzrostu wydajności, chyba że co minutę wykonuje się ogromną liczbę zadań.

Kultura uniksowa zawodzi. Moim skromnym zdaniem. :-)

Austin S.
źródło
1
„Brak dodatkowych zabezpieczeń”. To nie jest prawda. Spójrz na CVE-2011-1095 , CVE-2008-4304 i CVE-2010-3847 .
Nawiasem mówiąc, przegłosowałem twoją odpowiedź. Zazwyczaj staram się unikać odrzucania odpowiedzi nowo przybyłych, ale bezpieczeństwo jest dla mnie ważne. Proszę nie brać głosowania w niewłaściwy sposób. Oprócz części dotyczącej bezpieczeństwa, twoja odpowiedź jest doskonała i zasługuje na pochwałę. Możesz edytować swoją odpowiedź tutaj, jeśli chcesz.
Żadne z nich nie ma najmniejszego związku z tym, że cron używa powłoki z interaktywnym zestawem flag. To jest czysty FUD. Niestety nie mogę głosować za Twoją opinią. Może to wydawać się płomieniem, ale jest bardzo frustrujące, gdy ludzie myślą, że pojazd z trzema kołami jest lepszy, ponieważ istnieje problem bezpieczeństwa, aby założyć czwarte koło. To nie jest Ludzie jeździli na trójkołowym tak długo, że zapomnieli, że można dodać czwarte koło.
Austin S.,
Innymi słowy: jeśli któryś z zamierzonych dodatkowych obręczy zostanie użyty przez innych sugerowanych użytkowników, w jaki sposób nie uzyskają one dostępu do żadnej z wymienionych przez ciebie dziur? „* * * * * exec bash -i -c LOCALE = .......”
Austin S.,
To brzmi jak rant. Nawet nie wiem, gdzie w ogóle odpowiada na pytanie. Nawet jeśli część bezpieczeństwa została usunięta, @EvanTeitelman, nie rozumiem, dlaczego zasługuje na głosowanie, ponieważ nie odpowiada na pytanie.
Wildcard
1

Zamiast ustawiania profilu pomogło mi ustawienie PATH. Niektóre polecenia nie były dostępne w moich skryptach cron, ponieważ PATHsą różne.

ENVIRONMENT=prod
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

PATHPomagało mi ustawienie ścieżki poleceń. Jeszcze lepiej, jeśli możesz użyć szablonu i później zdetatalizować,

ENVIRONMENT={{ENVIRONMENT}}
PATH={{PATH}}
*/30 * * * * /opt/myscript1.sh
*/30 * * * * /opt/myscript2.sh
*/30 * * * * /opt/myscript3.sh

Przekazywanie zmiennych do każdego elementu wygląda na bałagan.

Optimus Prime
źródło
-1

Włożyłem . ~/.dbus/session-bus/*na górze mojego pożądanego skryptu :)

Eric
źródło
1
Witamy w U & L SE. Proszę rozszerzyć swoją odpowiedź, aby przyniosła korzyści czytelnikom.
Ramesh