Pertanyaan Menjalankan tugas cron secara manual dan langsung


(Saya sudah membaca Bagaimana saya bisa menguji skrip cron baru?.)

Saya memiliki masalah tertentu (cron job tidak muncul untuk dijalankan, atau berjalan dengan benar), tetapi masalahnya adalah umum: Saya ingin men-debug skrip yang diacak. Saya sadar bahwa saya dapat membuat garis * * * * * crontab, tetapi itu bukanlah solusi yang sepenuhnya memuaskan. Saya ingin dapat menjalankan tugas cron dari baris perintah seolah-olah cron menjalankannya (pengguna yang sama, variabel lingkungan yang sama, dll.). Apakah ada cara untuk melakukan ini? Harus menunggu 60 detik untuk menguji perubahan skrip tidaklah praktis.


94
2017-11-18 13:55




(Maaf tidak dapat menambahkan komentar) 0 30 16 20 *? * Bahkan jika Anda menjalankan pekerjaan seperti itu, seluruh ide adalah untuk menyediakan output skrip untuk melihat apa yang salah kecuali pekerjaan menulis ke log, ini adalah quuiet tidak berguna


Jawaban:


Inilah yang saya lakukan, dan tampaknya berhasil dalam situasi ini. Setidaknya, itu menunjukkan saya kesalahan, sedangkan menjalankan dari baris perintah sebagai pengguna tidak menunjukkan kesalahan.


Langkah 1: Saya menempatkan baris ini sementara di crontab pengguna:

* * * * *   /usr/bin/env > /home/username/tmp/cron-env

lalu mengeluarkannya begitu file itu ditulis.

Langkah 2: Membuat skrip bash run-as-cron kecil yang berisi:

#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"

Jadi, sebagai pengguna yang bersangkutan, saya bisa

run-as-cron /the/problematic/script --with arguments --and parameters

Solusi ini jelas dapat diperluas untuk menggunakan sudo atau semacamnya untuk fleksibilitas lebih.

Semoga ini bisa membantu orang lain.


73
2017-11-18 14:40



Ini tidak berhasil untuk saya dan saya bertanya-tanya apakah itu berlaku bagi siapa saja yang memberi suara. 1) Mengapa Anda menggunakan bash? Ini tidak diperlukan di sini dan mungkin tidak berlokasi di /usr/bin. 2) The cat …/cron-env menghasilkan beberapa baris, yang tidak berfungsi. Hanya mencoba untuk mengeksekusi /usr/bin/env -i $(cat cron-env) echo $PATH di terminal, ia mengeluarkan lingkungan secara harfiah alih-alih menggunakannya. 3) Lingkungan saat ini bocor ke dalam lingkungan cron yang diemulasi. Mencoba: export foo=leaked; run-as-cron echo $foo. - Marco
@Marco Works di bash, yang saya gunakan karena ini adalah lingkungan yang lebih baik daripada sh. Saya menggunakan segala sesuatu dari pdksh, ksh (beberapa versi), bash dan dash jadi saya sangat sadar akan perbedaan antara implementasi "murni" sh, bahkan ketika tetap sangat ketat dalam subset umum bahasa. :-) - Max Murphy
@Marco 2. cat menghasilkan beberapa baris, yang berfungsi, karena substitusi shell menciutkannya menjadi satu baris, yang dapat Anda periksa echo $(cat cron-env ) | wc; contoh perintah Anda, /usr/bin/env -i $(cat cron-env) echo $PATH, pengganti $PATH dari shell panggilan; alih-alih, ia harus memanggil subkulit untuk menggantikan di subenvironment, mis. /usr/bin/env -i $(cat cron-env) /bin/sh -c 'echo $PATH'. 3. Anda telah membuat kesalahan yang sama, lagi-lagi menggantikan dalam shell panggilan bukan di subenvironment - John Freeman


Saya menyajikan solusi berdasarkan jawaban Pistos, tetapi tanpa kekurangan.

  • Tambahkan baris berikut ke crontab, mis. menggunakan crontab -e

    * * * * *  /usr/bin/env > /home/username/cron-env
    
  • Buat skrip shell yang menjalankan perintah di lingkungan yang sama dengan tugas cron yang dijalankan:

    #!/bin/sh
    
    . "$1"
    exec /usr/bin/env -i "$SHELL" -c ". $1; $2"
    

Menggunakan:

run-as-cron <cron-environment> <command>

misalnya

run-as-cron /home/username/cron-env 'echo $PATH'

Perhatikan bahwa argumen kedua perlu dikutip jika membutuhkan argumen. Baris pertama dari skrip memuat shell POSIX sebagai interpreter. Baris kedua sumber file lingkungan cron. Ini diperlukan untuk memuat shell yang benar, yang disimpan dalam variabel lingkungan SHELL. Kemudian ia memuat lingkungan kosong (untuk mencegah bocornya variabel lingkungan ke dalam shell baru), meluncurkan shell yang sama yang digunakan untuk cronjobs dan memuat variabel lingkungan cron. Akhirnya perintah dijalankan.


34
2017-09-24 18:46



ini membantu saya untuk mereproduksi kesalahan memuat sphinx yang terkait dengan ruby. - cweiske
Saya menggunakan opsi cron @reboot untuk menulis file cron-env. Anda kemudian dapat meninggalkannya di crontab dan itu hanya akan ditulis ulang ketika sistem dimulai. Ini membuatnya sedikit lebih sederhana karena Anda tidak perlu menambahkan / menghapus garis. - Michael Barton


Karena crontab tidak melakukan pekerjaan itu, Anda akan memanipulasi kontennya:

crontab -l | grep -v '^#' | cut -f 6- -d ' ' | while read CMD; do eval $CMD; done

Apa yang dilakukannya:

  • daftar pekerjaan crontab
  • hapus baris komentar
  • hapus konfigurasi crontab
  • lalu luncurkan satu per satu

14
2017-08-19 19:45



Ini tidak harus dilakukan di lingkungan yang sama yang akan dilakukan oleh cron, dan saya pikir dia hanya ingin menguji salah satunya. - Falcon Momot
benar, saya telah salah ... Ini hanya menjalankan pekerjaan tetapi tidak seperti cron lakukan! - Django Janny
masih merupakan solusi luar biasa +1 - Eric Uldall


Secara default dengan sebagian besar daemon cron default yang saya lihat, tidak ada cara untuk menjalankan cron di sini sekarang. Jika Anda menggunakan anacron, mungkin saya berpikir untuk menjalankan turunan terpisah di latar depan.

Jika skrip Anda tidak berjalan dengan baik maka Anda tidak memperhitungkannya

  • skrip berjalan sebagai pengguna tertentu
  • cron memiliki lingkungan terbatas (manifestasi yang paling jelas dari ini adalah jalur yang berbeda).

Dari crontab (5):

Beberapa variabel lingkungan ditetapkan   naik secara otomatis oleh cron (8)   daemon. SHELL disetel ke / bin / sh, dan   LOGNAME dan HOME disetel dari   baris / etc / passwd dari crontab's   pemilik. PATH disetel ke "/ usr / bin: / bin".   HOME, SHELL, dan PATH mungkin   diganti oleh pengaturan di   crontab; LOGNAME adalah pengguna yang   pekerjaan sedang berjalan dari, dan mungkin tidak   berubah.

Secara umum PATH adalah masalah terbesar, jadi Anda perlu:

  • Secara eksplisit mengatur PATH di dalam skrip, saat menguji, ke / usr / bin: / bin. Anda dapat melakukan ini dengan bash ekspor PATH = "/ usr / bin: / bin"
  • Secara eksplisit mengatur PATH yang Anda inginkan di bagian atas crontab. misalnya PATH = "/ usr / bin: / bin: / usr / local / bin: / usr / sbin: / sbin"

Jika Anda perlu menjalankan skrip sebagai pengguna lain tanpa shell (misalnya www-data), gunakan sudo:

sudo -u www-data /path/to/crontab-script.sh

Hal pertama yang harus diuji sebelum semua itu, tentu saja, adalah skrip Anda benar-benar melakukan apa yang seharusnya dilakukan dari baris perintah. Jika Anda tidak dapat menjalankannya dari baris perintah, jelas tidak akan berfungsi dengan cron.


5
2017-11-18 14:27



Terima kasih atas tanggapannya yang menyeluruh. Saya menyadari dua masalah berjalan sebagai pengguna tertentu, dan dengan lingkungan tertentu. Dengan demikian, saya telah memformulasikan jawaban saya sendiri, yang sekarang akan saya posting ... - Pistos
Karakter Escape adalah alasan yang sah untuk pekerjaan yang tidak berjalan - Joe Phillips


Nah, pengguna sama dengan yang Anda masukkan ke entri crontab (atau yang crontab Anda masukkan ke dalam, bergantian), jadi itu tidak perlu dipikirkan. crontab(5) harus memberi Anda daftar variabel lingkungan yang ditetapkan, hanya ada beberapa.


1
2017-11-18 14:04



Dengan kata lain, Anda mengatakan tidak ada cara untuk melakukannya? Hanya solusi yang "cukup dekat"? - Pistos
Tidak, saya mengatakan bahwa Anda dapat melakukannya, menggunakan informasi yang saya berikan dalam jawaban saya. - womble♦


Di sebagian besar crontab seperti mis. vixie-cron Anda dapat menempatkan variabel dalam crontab itu sendiri seperti ini dan kemudian gunakan / usr / bin / env untuk memeriksa apakah berhasil. Dengan cara ini Anda dapat membuat skrip Anda bekerja di crontab setelah Anda menemukan apa yang salah dengan skrip run-as-cron.

SHELL=/bin/bash
LANG=en
FASEL=BLA

* * * * *   /usr/bin/env > /home/username/cron-env

1
2017-10-27 06:52





Naskah Marco tidak berlaku untukku karena suatu alasan. Saya tidak punya waktu untuk melakukan debug, jadi saya menulis skrip Python yang melakukan hal yang sama. Ini lebih lama, tetapi: pertama, ini bekerja untuk saya, dan kedua, saya merasa lebih mudah untuk dipahami. Ubah "/ tmp / cron-env" ke tempat Anda menyimpan lingkungan Anda. Ini dia:

#!/usr/bin/env python
from __future__ import division, print_function

import sys
import os

def main():
    if len(sys.argv) != 2 or sys.argv[1] in ('-h', '--help'):
        print("Usage: {} CMD\n"
              "Run a command as cron would. Note that CMD must be quoted to be only one argument."
              .format(sys.argv[0]))
        sys.exit(1)
    _me, cmd = sys.argv
    env = dict(line.strip().split('=', 1) for line in open('/tmp/cron-env'))
    sh = env['SHELL']
    os.execvpe(sh, [sh, '-c', cmd], env)

if __name__ == '__main__':
    main()

1
2017-12-24 08:48





Solusi Marco tidak bekerja untuk saya tetapi skrip python Noam bekerja. Berikut ini sedikit modifikasi pada skrip Marco yang membuatnya bekerja untuk saya:

#!/bin/sh
. "$1"
exec /usr/bin/env -i "$SHELL" -c "set -a;. $1; $2"

Yang ditambahkan set -a variabel ekspor didefinisikan dalam skrip $ 1 dan membuatnya tersedia untuk perintah $ 2

p.s. Piton Noam bekerja karena ia 'mengekspor' lingkungan ke proses anak.


1
2018-05-11 05:05





Saya belum pernah menemukan cara untuk menjalankan cron job secara manual tetapi ini Tulisan menyarankan pengaturan lingkungan yang sama seperti cronjob akan memiliki dan menjalankan skrip secara manual.


0
2017-11-18 14:07



Bukankah yang Anda sarankan untuk melakukan apa yang OP ingin tahu bagaimana melakukannya? - womble♦
Itulah mengapa saya memasukkan tautan ke artikel yang menjelaskan cara melakukannya. Saya pikir tidak perlu menyalin-tempel semuanya di sini. - oneodd1


Anda dapat memprogram pekerjaan untuk memulai menit berikutnya :)


0
2017-09-23 13:52



59 detik adalah waktu yang banyak. - Stéphane Bruckert
OP menyebutkan kemungkinan ini dalam pertanyaan: "Apakah ada cara untuk melakukan ini? Harus menunggu 60 detik untuk menguji perubahan skrip tidak praktis." - Andrew Grimm
59 detik mungkin kurang dari yang diperlukan untuk memilih dan mengimplementasikan solusi lain yang diusulkan (dan tidak dijamin untuk dikerjakan). Ketika saya melihat kekurangan seperti itu, saya bertanya-tanya bagaimana Linux menjadi seperti server standar de-facto. Tidakkah sysadmin yang serius ingin menguji pekerjaan mereka? - Rolf


Jika itu skrip shell, ini harus membuat Anda lebih banyak dari jalan:

sudo su  # (assuming it's run as root, if not switch to the user you want it to run as)
cd  # Switch to home folder
sh <full-path/my-shell-script>

Ini pasti akan menyoroti beberapa masalah, jika tidak semuanya.


0
2018-04-04 17:16