Bagaimana saya bisa menjalankan perintah cron dengan variabel lingkungan yang ada?


114

Bagaimana saya bisa menjalankan perintah cron dengan variabel lingkungan yang ada?

Jika saya berada di prompt shell saya bisa mengetik echo $ORACLE_HOMEdan mendapatkan path. Ini adalah salah satu variabel lingkungan saya yang akan ditetapkan di saya ~/.profile. Namun, sepertinya ~/.profileskrip fron cron tidak dapat dimuat dan skrip saya gagal karena $ORACLE_HOMEvariabel tidak disetel.

Dalam pertanyaan ini penulis menyebutkan membuat ~/.cronfileprofil yang mengatur variabel untuk cron, dan kemudian ia melakukan solusi untuk memuat semua perintah cronnya ke dalam skrip yang disimpannya di ~/Crondirektori. File seperti ~/.cronfileterdengar seperti ide yang bagus, tetapi sisa jawabannya tampaknya sedikit rumit dan saya berharap seseorang dapat memberi tahu saya cara yang lebih mudah untuk mendapatkan hasil yang sama.

Saya kira di awal skrip saya, saya bisa menambahkan sesuatu seperti source ~/.profiletapi itu sepertinya bisa berlebihan.

Jadi bagaimana saya bisa membuat skrip cron saya memuat variabel dari profil shell-interaktif saya?


Bagaimana menambahkan source ~/.profileke dalam suatu program mubazir? Program mewarisi lingkungannya dari program panggilan. Jika program panggilan itu bukan shell Anda, lalu bagaimana program yang akan mendapatkan lingkungan yang Anda inginkan?
Arcege

Saya sudah menulis jawaban saya untuk pertanyaan serupa di sini. Ini hanya digunakan su -luntuk mensetup lingkungan login normal termasuk $ PATH untuk root atau pengguna tertentu lainnya.
tasket

Jawaban:


141

Di crontab, sebelum Anda memerintahkan, tambahkan . $HOME/.profile. Sebagai contoh:

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

Crontidak tahu apa-apa tentang cangkang Anda; dimulai oleh sistem, sehingga memiliki lingkungan minimal. Jika Anda menginginkan sesuatu, Anda harus membawa itu ke dalam diri Anda.


14
Apa yang dilakukan .sebelum skrip? (tidak yakin bagaimana saya melakukannya man). Mengapa ini berbeda source?
cwd

25
The .perintah perintah asli untuk source. Mereka setara dalam shell dan sedikit lebih mudah untuk diketik, terutama di dalam crontab. Untuk mendapatkan info lebih lanjut, ketik help .atau cari ^SHELL BUILTIN COMMANDSdi halaman manual untuk bashatau di bagian atas tipe man zshbuiltins .` . Running akan memberi tahu Anda bahwa perintahnya adalah builtin.
Arcege

9
Tergantung pada distribusi Linux, Anda mungkin perlu mengubah .profileoleh .bash_profile. Periksa .profilefile mana yang ada di direktori home pengguna.
Frosty Z

@Arcege Ini tidak berfungsi untuk saya (Fedora Core 21), dan saya kira itu karena level shell turun kembali. Alih-alih, yang TIDAK berfungsi adalah jika Anda sumbernya.
Richard T

3
Kemungkinan jika tidak berfungsi, itu karena SHELL untuk skrip cron tidak disetel ke bash, jadi itu tidak mengeksekusi dengan cara yang sama seperti yang Anda harapkan.
Daniel Farrell

40

Pilihan lain, yang menurut saya lebih mudah, adalah menjalankan skrip dengan cron dan memiliki lingkungan dalam skrip.

Dalam file crontab -e:

SHELL=/bin/bash

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

Dalam file cron_job.sh:

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

Perintah apa pun setelah sumber .bash_profile akan memiliki lingkungan Anda seolah-olah Anda masuk.


5
Ketika menjalankan AMI AWS Linux, bahkan tidak terpikir oleh saya bahwa cron tidak akan digunakan /bin/bashsebagai shell. Saya terus bertanya-tanya mengapa hal-hal seperti cd /path/to/project; source .varsakan berfungsi ketika saya mengetik secara manual tetapi akan gagal ( File not found) ketika dimasukkan dalam cronjob. Baris kunci bagi saya adalah pengaturan SHELL=/bin/bashsehingga saya benar-benar bisa menggunakan perintah bash yang sudah dikenal di setiap cronjob. /bin/sh/(cron shell default, tampaknya) sangat terbatas.
Hartley Brody

Sayang sekali Anda tidak dapat menentukan File Lingkungan di bagian atas cron seperti Anda dapat menentukan variabel lingkungan individu. Systemd memiliki EnvironmentFileunit layanan. Sayang sekali cron tidak memiliki yang serupa.
radtek

Anda FORCE semua skrip untuk menggunakan / bin / bash di semua crontab, yang bukan ide yang baik, juga apa tentang baris cron Anda: * / 1 * * * * $ HOME / cron_job.sh… * / 1 baik untuk APA ?!? satu bintang berarti akan dieksekusi setiap menit / 1 berarti akan dieksekusi setiap menit, sebagai jawaban di komunitas yang cerdas ini adalah dosa yang tidak menyenangkan, sekarang saya percaya Anda sangat bingung untuk mengatakan yang terbaik ... maaf
PENULIS

1
Inilah yang disebut sebagai contoh. Jangan ragu untuk menyesuaikan dengan kebutuhan Anda atau tidak menggunakannya sama sekali. Stroke berbeda untuk orang yang berbeda.
Robert Brisita

4
Jika $SHELLadalah /bin/sh, yang sourceperintah tidak ada. Gunakan .sebagai gantinya.
Melle

18

Opsi lain, yang menurut saya lebih mudah, adalah menjalankan skrip dengan cron dan menyuruh bash untuk masuk (karenanya menggunakan /etc/profile.d/...definisi lingkungan)

Dalam crontab -efile:

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

Perintah apa pun setelah sumber .bash_profileakan memiliki lingkungan Anda seolah-olah Anda masuk.


10

Ide buruk. Praktik umum adalah secara khusus mengatur semua variabel lingkungan yang diperlukan dalam skrip yang akan dijalankan dari pekerjaan cron.


Saya setuju dengan @fpmurphy, bahwa cara-cara itu juga memastikan lingkungan proses yang aman. Jika Anda ingin mengatur hanya beberapa variabel dari cron, Anda dapat menggunakan /usr/bin/envperintah untuk mengatur variabel dan kemudian dapat bertindak sebagai proses lingkungan untuk cronjob.
Nikhil Mulley

daemontools jugaenvdir muncul dalam pikiran.
sr

6
Saya semua untuk keamanan, tetapi mungkin saya dapat membuat file ~/.cronvarsdan memasukkannya ke dalam profil dan juga dalam skrip cron saya. Saya tidak ingin variabel lingkungan kode keras di setiap skrip saya jalankan karena ketika jalur mengubah jalur kode keras di setiap file tidak mudah untuk dipelihara. Sepertinya itu akan memungkinkan tempat tersentralisasi untuk variabel yang diperlukan dan tetap menjaga variabel lainnya dari tidak dimuat.
cwd

4

Sintaks ini pasti membantu Anda. Saya tidak mengerti sintaksnya, tetapi itu berhasil. Oracle menggunakan sintaks ini, ketika menyebarkan Oracle Configuration Manager ke crontab, oleh karena itu, saya percaya bahwa ini adalah solusi yang tepat.

0 5 * * * SOME_ENV_VAR=some_value some_command some_parameters

2

Saya baru-baru ini menemukan sebuah kasus di mana saya harus menjalankan cronjob secara keseluruhan sebagai root tetapi, pada saat yang sama, harus menjalankan sub-perintah sebagai pengguna yang berbeda (yang membutuhkan sumber lingkungan pengguna itu). Saya pergi dengan pendekatan berikut:

# 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

Bagian penting adalah argumen -iyang diteruskan ke sudomana akan menjalankan perintah yang diberikan dalam shell login yang terpisah (yang pada gilirannya berarti bahwa dotfile pengguna akan bersumber).

PS: Perhatikan bahwa userkolom hanya tersedia di dalam /etc/crontabdan /etc/cron.d/*file.


1

Solusinya, yang bekerja untuk saya, dijelaskan di sini .

Anda membuat skrip pembungkus, yang memanggil . ~/.cronfile, dan kemudian melakukan hal-hal yang Anda inginkan. Script ini diluncurkan oleh cron.

Di ~/.cronfileAnda tentukan lingkungan untuk pekerjaan cron Anda.


1

Ya, Anda dapat menggunakan "solusi terkenal" (beberapa di antaranya telah terdaftar). Ini adalah cara lain untuk mengatakan bahwa semua orang tahu itu jelek, meskipun beberapa orang akan menyebut ini sebagai "fitur keamanan" karena mereka telah menghabiskan setidaknya sebanyak tersandung kegagalan ini (ure) seperti yang Anda miliki, dan ingin berpikir mereka buang waktu bukan untuk sia-sia. Ini setara dengan cron dari keyboard QWERTY.

Saya menduga alasan aslinya mungkin karena kinerja, sehingga skrip berjalan sekali dalam satu menit tidak akan menghabiskan waktu untuk membaca skrip rc. Awalnya cron juga tidak benar-benar dapat dikonfigurasi, jadi default adalah satu-satunya pilihan.

Tidak ada keamanan tambahan dengan tidak memiliki beberapa konfigurasi atau metode sederhana untuk memiliki cron hanya mengambil lingkungan shell interaktif Anda alih-alih pengguna harus melakukan senam shell bodoh. Pada mesin modern umumnya tidak ada perolehan kinerja yang jelas kecuali Anda memiliki banyak pekerjaan yang berjalan setiap menit.

Budaya Unix gagal. Menurut pendapat saya. :-)


1
"Tidak ada keamanan tambahan." Itu tidak benar. Lihatlah CVE-2011-1095 , CVE-2008-4304 , dan CVE-2010-3847 .

Ngomong-ngomong, saya menurunkan jawaban Anda. Saya biasanya mencoba untuk menghindari downvoting jawaban pendatang baru tetapi keamanan penting bagi saya. Tolong jangan mengambil downvote dengan cara yang salah. Selain bagian tentang keamanan, jawaban Anda sangat bagus dan layak mendapat dukungan. Anda dapat mengedit jawaban Anda di sini jika mau.

Tidak ada dari mereka yang memiliki sedikit pun hubungannya dengan memiliki cron menggunakan shell dengan set flag interaktif. Ini murni FUD. Sayangnya saya tidak bisa downvote downvote Anda. Ini mungkin tampak seperti nyala api, tetapi sangat menyebalkan ketika orang berpikir kendaraan dengan roda tiga lebih baik karena ada masalah keamanan untuk memakai roda keempat. Bukan itu. Orang-orang baru saja mengendarai sepeda roda tiga begitu lama sehingga mereka lupa untuk menambahkan roda keempat.
Austin S.

Dengan kata lain: jika ada simpai ekstra yang dimaksudkan yang dijawab penjawab lain digunakan, bagaimana mereka juga tidak mendapatkan akses ke lubang yang Anda sebutkan? "* * * * * exec bash -i -c LOCALE = ......."
Austin S.

Ini terdengar seperti kata-kata kasar. Saya bahkan tidak melihat di mana itu menjawab pertanyaan sama sekali. Bahkan jika bagian keamanan telah dihapus, @EvanTeitelman, saya tidak melihat mengapa itu layak mendapat upvote karena tidak menjawab pertanyaan.
Wildcard


1

Alih-alih mengatur profil, yang membantu saya adalah mengatur PATH. Beberapa perintah tidak tersedia di skrip cron saya karena PATHberbeda.

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

Pengaturan PATHdengan jalur perintah membantu saya. Lebih baik lagi jika Anda dapat menggunakan templat dan melakukan detemplatize nanti,

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

Melewati variabel ke setiap item terlihat berantakan.


-1

Saya menempatkan. ~/.dbus/session-bus/*di bagian atas skrip yang saya inginkan :)


1
Selamat datang di U&L SE. Harap perluas jawaban Anda lebih banyak sehingga akan menguntungkan pembaca.
Ramesh
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.