Bir cron komutunu mevcut çevresel değişkenlerle nasıl çalıştırabilirim?


114

Bir cron komutunu mevcut çevresel değişkenlerle nasıl çalıştırabilirim?

Bir kabuk isteminde iseniz echo $ORACLE_HOMEve bir yol alabilirim. Bu benim içime giren çevresel değişkenlerimden biri ~/.profile. Bununla birlikte, ~/.profilefron cron komut dosyalarının yüklenmediği ve $ORACLE_HOMEdeğişken ayarlanmadığı için komut dosyalarımın başarısız olduğu görünüyor .

Gelen bu soruya yazar oluşturarak bahseder ~/.cronfilecron için değişkenleri kurar profili ve sonra kendisine sakladığı komut içine bütün cron komutları yüklemek için bir çözüm yapar ~/Crondizine. ~/.cronfileKulağa hoş bir fikir gibi geliyor, ama cevabın geri kalanı biraz hantal görünüyor ve birinin bana aynı sonucu almanın kolay bir yolunu söyleyebileceğini umuyordum.

Sanırım senaryolarımın başında bir şeyler ekleyebilirim source ~/.profileama gereksiz gibi görünüyor.

Peki, cron scriptlerimin değişkenleri interaktif-kabuk profilimden yüklemesini nasıl sağlayabilirim?


source ~/.profileBir programa fazlalık nasıl eklenir ? Programlar, çevrelerini çağıran programdan devralır. Eğer bu arama programı sizin kabuğunuz değilse, o zaman decendant programı istediğiniz ortamı nasıl elde eder?
Arcege

Burada da benzer bir soruya cevabımı yazdım . Basitçe, su -lroot veya başka bir kullanıcı için $ PATH dahil normal bir giriş ortamı oluşturmak için kullanılır.
tasket

Yanıtlar:


141

Crontab'da, komut vermeden önce ekleyin . $HOME/.profile. Örneğin:

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

Cronkabuğun hakkında hiçbir şey bilmiyor; sistem tarafından başlatılır, bu nedenle minimal bir ortama sahiptir. Bir şey istiyorsan, bunu kendine getirmen gerekir.


14
.Senaryodan önce ne yapar ? (nasıl yapacağımdan emin değilim man). Bu neden farklı source?
cwd

25
.Komut için orijinal komuttur source. Kabuk içinde eşdeğerdir ve özellikle bir crontab içinde yazması biraz daha kolaydır. Daha fazla bilgi almak help .için ^SHELL BUILTIN COMMANDS, man sayfasında zshbuiltins tipini yazın bashveya üstüne yazın. `Komutun bir yerleşik olduğunu söyleyecektir. man . Running
Arcege

9
Linux dağıtımlarına bağlı olarak, .profiletarafından değiştirmeniz gerekebilir .bash_profile. .profileKullanıcının giriş dizininde hangi dosyanın bulunduğunu kontrol edin .
Frosty Z

@ Arcege Bu benim için işe yaramıyor (Fedora Core 21) ve bunun nedeni, kabuk seviyesinin düşmesidir. Bunun yerine, kaynak yaparsanız işe yarar.
Richard T

3
Çalışmıyorsa, bunun nedeni cron betiği için SHELL'in bash olarak ayarlanmamış olmasıdır, bu nedenle beklediğiniz şekilde yürütülmez.
Daniel Farrell

40

Daha kolay bulduğum bir diğer seçenek de betiği cron ile çalıştırmak ve betiğin içinde ortamın bulunması.

Crontab -e dosyasında:

SHELL=/bin/bash

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

Cron_job.sh dosyasında:

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

.Bash_profile kaynağından sonraki herhangi bir komut, giriş yapmış gibi ortamınıza sahip olacaktır.


5
Bir AWS Linux AMI ile çalışırken, cronun /bin/bashkabuk olarak kullanmayacağı bile aklıma gelmedi . cd /path/to/project; source .varsOnları elle yazarken neden işe yarayacağını ama File not foundbir cronjob'a dahil edildiğinde ( ) başarısız olacağını merak etmeye devam ettim . Benim için kilit nokta SHELL=/bin/bash, her cronjob için tanıdık bash komutlarını kullanabilmem için ayardı . /bin/sh/(görünüşte varsayılan cron kabuğu) çok sınırlayıcıdır.
Hartley Brody

Tek tek ortam değişkenleri belirleyebileceğiniz gibi cronun tepesinde Çevre Dosyaları belirtemezsiniz. Systemd bir EnvironmentFileservis birimine sahiptir. Çok kötü cron benzer bir şey yok.
radtek

Tüm komut dosyalarını / bin / bash komutunu tüm crontab'larda kullanmaya zorluyorsunuz, bu iyi bir fikir değil, aynı zamanda cron satırınızla ilgili: * / 1 * * * * $ HOME / cron_job.sh… * / 1 WHAT için iyidir ?!? bir yıldız her dakika çalıştırılacağı anlamına gelir / 1 her dakika çalıştırılacak anlamına gelir, akıllı bir toplulukta verilen cevap kötü bir günahtır, şimdi en iyisini söylemek için
kafanızın

1
Buna örnek denir. İhtiyaçlarınızı ayarlamaktan çekinmeyin veya hiç kullanmayın. Farklı insanlar için farklı vuruşlar.
Robert Brisita,

4
Eğer $SHELLöyleyse /bin/sh, sourcekomut mevcut değil. Yerine .kullanın.
Melle

18

Daha kolay bulduğum bir diğer seçenek ise betiği cron ile çalıştırmak ve bash'a giriş yapmasını söylemek (böylece /etc/profile.d/...ortam tanımlarını kullanarak ).

In crontab -edosyası:

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

Kaynağından sonraki herhangi bir komut, .bash_profilegiriş yapmış gibi ortamınıza sahip olacaktır.


10

Kötü bir fikir. Genel uygulama, gerekli tüm çevresel değişkenleri, bir cron işinden çalıştırılacak olan bir komut dosyasında özel olarak ayarlamaktır.


Fpmurphy ile aynı fikirdeyim, bu da güvenli süreç ortamını garanti etmenin bu yoludur. Eğer cron'dan sadece birkaç değişken ayarlamak istiyorsanız /usr/bin/env, değişkenleri ayarlamak için komutu kullanabilir ve daha sonra cronjob için ortam işlemi yapabilir.
Nikhil Mulley

daemontools 'envdir da akla geliyor.
sr_

6
Ben tamamen güvenlikten geliyorum ama belki bir dosya oluşturabilirim ~/.cronvarsve bunu profilde ve aynı zamanda cron betiklerime ekleyebilirim . Çalıştırdığım komut dosyalarının her birinde çevresel değişkenleri kodlamak istemiyorum çünkü yollar her dosyadaki sabit kodlu yolları değiştirdiğinde bakımı kolay değildir. Bu, ihtiyaç duyulan değişkenler için merkezi bir yere izin verecek ve diğer değişkenlerin yüklenmesini engellemeye devam edecek gibi görünüyor.
cwd

4

Bu sözdizimi kesinlikle size yardımcı olur. Sözdizimini anlamıyorum ama işe yarıyor. Oracle bu sözdizimini kullanır, Oracle Configuration Manager'ı crontab olarak dağıtırken, bunun doğru bir çözüm olduğuna inanıyorum.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters

2

Geçenlerde genel cronjob'ı root olarak çalıştırmak zorunda kaldığım bir durumla karşılaştım, fakat aynı zamanda farklı bir kullanıcı olarak bir alt komut çalıştırmak zorunda kaldım (ki bu kullanıcının ortamının kaynaklanması gerekiyordu). Aşağıdaki yaklaşımla gittim:

# 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

Önemli bir parçası argümanı -igeçirilen ediliyor sudo(sırayla kullanıcının dotfiles kaynaklı olacağı anlamına gelir) ayrı bir giriş kabuğu verilen komutu yerine getirecektir hangi.

Not: userSütunun sadece dosyalarda /etc/crontabve /etc/cron.d/*dosyalarda mevcut olduğunu unutmayın .


1

Benim için işe yarayan çözüm burada açıklanmaktadır .

Çağıran . ~/.cronfileve istediğiniz şeyleri yapan bir sarmalayıcı komut dosyası oluşturursunuz . Bu komut cron tarafından başlatıldı.

In ~/.cronfilesize cron işleri için çevreyi belirtin.


1

Evet, "iyi bilinen geçici çözümleri" kullanabilirsiniz (birkaç tanesi listelenmiştir). Bu, herkesin berbat olduğunu bildiğini söylemenin başka bir yoludur, ancak bazı insanlar bunu “güvenlik özelliği” olarak niteleyeceklerdir; boşa zaman boşa değildi. QWERTY klavyenin cron eşdeğeridir.

Asıl nedenin performans için olabileceğinden şüpheleniyorum, öyle ki dakikada bir kez çalışan komut dosyaları, rc komut dosyalarını okumak için zaman harcamaz. Ayrıca başlangıçta cron gerçekten yapılandırılabilir değildi, bu yüzden bir varsayılan gerçekten tek seçimdi.

Aptal deniz jimnastiği yapmak zorunda kalan kullanıcılar yerine etkileşimli kabuğunuzun ortamını cron yapmak için basit bir konfigürasyon ya da metoda sahip olmadıklarından ek güvenlik yoktur. Modern bir makinede, her dakika çok fazla işiniz olmadıkça, genellikle algılanabilir bir performans kazancı olmaz.

Unix kültürü başarısız. Benim düşünceme göre. :-)


1
"Ek güvenlik yok." Bu doğru değil. Bir göz atın CVE-2011-1095 , CVE-2008-4304 , ve CVE-2010-3847 .

Bu arada cevabını reddettim. Genelde yeni gelenlerin cevaplarını azaltmaktan kaçınmaya çalışırım ancak güvenlik benim için önemlidir. Lütfen yanlış yere oy kullanmayın. Güvenlikle ilgili bölümün yanı sıra, cevabınız mükemmel ve bir artı oy hak ediyor. İsterseniz cevabınızı burada düzenleyebilirsiniz .

Bunların hiçbiri cron'un interaktif bayrak takımıyla bir kabuk kullanmasıyla ilgili en ufak bir şeye sahip değil. Bu saf FUD. Maalesef, indiriminizi reddedemem. Bu bir alev gibi görünebilir, ancak insanlar üç tekerlekli bir aracın daha iyi olduğunu düşündükleri için çok sinir bozucu çünkü dördüncü bir çarkı takacak bir güvenlik sorunu var. Değil. İnsanlar çok uzun zamandır üç tekerlekli bisiklet sürdüler, dördüncü bir tekerlek eklemenin mümkün olduğunu unuttular.
Austin S.

Başka bir deyişle: Amaçlanan ilave çemberlerden herhangi biri önerildiyse önerilen diğer cevaplayıcılar kullanılırsa, bahsettiğiniz deliklerden hiçbirine erişemezler mi? "* * * * * exec bash -i -c LOCALE = ......."
Austin S.

Bu bir rant gibi okuyor. Soruyu nerede cevapladığını bile anlamadım. Güvenlik bölümü kaldırılmış olsa bile, @EvanTeitelman, soruyu cevaplamadığı için neden bir olumlu oyu hak ettiğini anlamıyorum.
Joker


1

Profil belirlemek yerine, bana yardımcı olan şey onu ayarlamaktı PATH. Bazı komutlar PATHfarklı olduğu için cron komut dosyalarımda mevcut değildi .

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

PATHKomutların yolu ile ayarlama bana yardımcı oldu. Daha da iyisi, bir şablon kullanabilir ve daha sonra yanlış tanıyabilirseniz

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

Değişkenleri her bir öğeye geçirmek karışık görünüyor.


-1

Koydum . ~/.dbus/session-bus/*İstediğim betiğin başında :)


1
U & L SE'ye hoş geldiniz. Lütfen cevabınızı, okuyuculara fayda sağlayacak şekilde daha da genişletin.
Ramesh
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.