Soru Elle ve hemen bir cron işi çalıştırmak


(Zaten okudum Yeni bir cron betiğini nasıl test edebilirim?.)

Belirli bir sorunum var (cron işi çalıştırılmıyor veya düzgün çalışıyor), ancak sorun genel: Ben cronned scripts hata ayıklamak istiyorum. Bir * * * * * crontab satırı kurabileceğimin farkındayım, ancak bu tamamen tatmin edici bir çözüm değil. Komut satırından cron çalıştırıyormuş gibi bir cron işi yapabilmeyi isterim (aynı kullanıcı, aynı ortam değişkenleri, vs.). Bunu yapmanın bir yolu var mı? Komut dosyası değişikliklerini test etmek için 60 saniye beklemek pratik değildir.


94
2017-11-18 13:55


Menşei


(özür dilerim yorum yapamaz) 0 30 16 20 *? * İşi böyle çalıştırsanız bile, tüm iş, bir günlük için yazmazsa neyin yanlış gittiğini görmek için komut dosyası çıkışı sağlamaktır, bu işe yaramazsa


Cevaplar:


İşte yaptım ve bu durumda çalışıyor gibi görünüyor. En azından, bana hata gösterir, oysa kullanıcı hata göstermezken komut satırından çalışır.


Aşama 1: Bu satırı kullanıcının crontab'ına geçici olarak koydum:

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

sonra dosya yazdıktan sonra çıkardı.

Adım 2: Kendimi içeren küçük bir run-cron bash betiği yaptım:

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

Öyleyse, söz konusu kullanıcı olarak,

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

Bu çözüm, sudo kullanımını ya da daha fazla esneklik sağlamak için açık bir şekilde genişletilebilir.

Umarım bu başkalarına yardımcı olur.


73
2017-11-18 14:40



Bu benim için işe yaramıyor ve merak eden kimse için var mı merak ediyorum. 1) Neden bash kullanıyorsunuz? Burada gerekli değildir ve bu yer olmayabilir /usr/bin. 2) cat …/cron-env çalışmayan birden çok satır çıkarır. Sadece yürütmeye çalış. /usr/bin/env -i $(cat cron-env) echo $PATH Terminalde, tam anlamıyla kullanmak yerine çevreyi çıkarır. 3) Mevcut ortam, taklit edilen cron ortamına sızar. Deneyin: export foo=leaked; run-as-cron echo $foo. - Marco
@Marco Works in bash, bu benim kullandığım şeyden daha iyi tanımlanmış bir ortam. Ben pdksh, ksh (birden çok sürüm), bash ve tire her şeyi kullanıyorum, bu yüzden dillerin ortak alt kümesinde çok sıkı kalırken bile, "saf" ın uygulamaları arasındaki farkların çok farkındayım. :-) - Max Murphy
2.Marco 2. cat İşe yarayan birden fazla satır çıkarır, çünkü kabuk değiştirmesi bunları tek bir satıra daraltır. echo $(cat cron-env ) | wc; senin örnek komutun /usr/bin/env -i $(cat cron-env) echo $PATH, yerine $PATH arayan kabuktan; bunun yerine, alt çevrede yer almak için bir alt-kabuğu çağırmalıdır, örn. /usr/bin/env -i $(cat cron-env) /bin/sh -c 'echo $PATH'. 3. Aynı hatayı yaptınız, yine alt çevrede yerine arama kabuğunun yerine geçtiniz. - John Freeman


Pistos cevabına dayanan, ancak kusurları olmayan bir çözüm önerdim.

  • Aşağıdaki satırı crontab'a ekleyin, ör. kullanma crontab -e

    * * * * *  /usr/bin/env > /home/username/cron-env
    
  • Aynı ortamda cron işlerinin çalıştırıldığı bir komutu çalıştıran bir kabuk betiği oluşturun:

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

kullanın:

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

Örneğin.

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

Bir argüman gerektiriyorsa ikinci argümanın alıntılanması gerektiğini unutmayın. Komut dosyasının ilk satırı, bir POSIX kabuğunu yorumlayıcı olarak yükler. İkinci satır, cron ortam dosyasını oluşturur. Bu ortam değişkeni içinde depolanan doğru kabuğu yüklemek için gereklidir SHELL. Ardından boş bir ortam yükler (ortam değişkenlerinin yeni kabuk içine sızmasını önlemek için), cronjobs için kullanılan ve cron ortam değişkenlerini yükleyen aynı kabuğu başlatır. Sonunda komut yürütülür.


34
2017-09-24 18:46



Bu benim yakut ile ilgili sphinx yükleme hatasımı yeniden oluşturmama yardımcı oldu. - cweiske
Cron-env dosyasını yazmak için @reboot cron seçeneğini kullandım. Daha sonra crontab içinde bırakabilirsiniz ve sistem başlatıldığında sadece yeniden yazılabilir. Satır eklemek / çıkarmak zorunda kalmayacağınız için biraz daha basittir. - Michael Barton


Crontab bu işi yapmadığı için, içeriği değiştirirsiniz:

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

Bu ne yapar :

  • crontab işlerini listeler
  • yorum satırlarını kaldır
  • crontab yapılandırmasını kaldır
  • sonra onları tek tek başlat

14
2017-08-19 19:45



Bu zorunlu olarak cronun aynı ortamda yapmasını gerektirmiyor ve ben de onlardan sadece birini test etmek istediğini düşündüm. - Falcon Momot
Doğru, yanılmışım ... Sadece işleri yerine getirir ama cron yapar gibi olmaz! - Django Janny
hala harika bir çözüm +1 - Eric Uldall


Varsayılan olarak gördüğüm çoğu varsayılan cron daemon'ları ile, şu anda cronun şu anda koşmasını söylemek için hiçbir yol yoktur. Anacron kullanıyorsanız, ön planda ayrı bir örnek çalıştırmayı düşünüyorum.

Komut dosyalarınız düzgün çalışmıyorsa, hesaba katılmıyorsunuz demektir.

  • komut dosyası belirli bir kullanıcı olarak çalışıyor
  • cron kısıtlı bir ortama sahiptir (bunun en bariz tezahürü farklı bir yoldur).

Crontab'tan (5):

Çeşitli ortam değişkenleri ayarlandı   cron tarafından otomatik olarak açılır (8)   cini. SHELL / bin / sh olarak ayarlandı ve   LOGNAME ve HOME,   crontab’ın / etc / passwd satırı   sahip. PATH "/ usr / bin: / bin" olarak ayarlandı.   HOME, SHELL ve PATH olabilir   ayarlarında geçersiz kılınmış   crontab; LOGNAME kullanıcı   iş çalışıyor ve olmayabilir   değişti.

Genel olarak PATH en büyük problemdir, bu yüzden yapmanız gerekenler:

  • PATH komut dosyasında, test ederken / usr / bin: / bin dizinine açıkça ayarlayın. Bunu bash ile yapabilirsiniz PATH = "/ usr / bin: / bin" dışa aktarma
  • Crontab'ın en üstünde istediğiniz doğru PATH'ı açıkça ayarlayın. Örneğin. PATH = "/ usr / bin: / bin: / usr / local / bin: / usr / sbin / sbin"

Komut dosyasını bir kabuk olmadan başka bir kullanıcı olarak çalıştırmanız gerekiyorsa (ör. Www-data), sudo kullanın:

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

Tüm bunlardan önce test edilecek ilk şey, tabiki, komut dosyanızın komut satırından ne yapması gerektiğini gerçekten yapmasıdır. Komut satırından çalıştıramazsanız, açıkça cron ile çalışmaz.


5
2017-11-18 14:27



Tam cevap için teşekkür ederim. Belirli bir kullanıcı olarak ve belirli bir ortamla çalışmanın iki meselesinin farkındayım. Bu yüzden, şimdi cevaplayacağım kendi cevabımı formüle ettim ... - Pistos
Kaçış karakterleri, işe yaramayan iş için geçerli bir nedendir. - Joe Phillips


Peki, kullanıcı crontab girişine koyduğunuzla aynıdır (veya crontab'ı dönüşümlü olarak yerleştirirsiniz), yani bu bir no-brainerdır. crontab(5) ayarladığınız ortam değişkenlerinin listesini vermelidir, sadece birkaçı vardır.


1
2017-11-18 14:04



Başka bir deyişle, bunu yapmanın bir yolu olmadığını mı söylüyorsun? Yalnızca "yeterince yakın" geçici çözümler var mı? - Pistos
Hayır, cevabımda verdiğim bilgileri kullanarak bunu yapabileceğinizi söylüyorum. - womble♦


Çoğu crontabs gibi, ör. vixie-cron değişkenlerini crontab'ın kendisinde olduğu gibi yerleştirebilir ve sonra çalışıp çalışmadığını kontrol etmek için / usr / bin / env komutunu kullanabilirsiniz. Bu şekilde, sen-cron betiği ile yanlış olanı bulduğunda senaryonun crontab içinde çalışmasını sağlayabilirsiniz.

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

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

1
2017-10-27 06:52





Marco'nun senaryosu bir sebepten dolayı benim için çalışmadı. Hata ayıklamak için zamanım olmadı, ben de aynı şeyi yapan bir Python betiği yazdım. Daha uzun, ama: önce, benim için çalışıyor ve ikincisi, anlaması daha kolay. Ortamınızı kaydettiğiniz yeri "/ tmp / cron-env" olarak değiştirin. İşte burada:

#!/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





Marco'nun çözümü benim için çalışmadı ama Noam'ın python senaryosu işe yaradı. İşte Marco'nun senaryosunun benim için çalışmasını sağlayan küçük bir değişiklik:

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

Ekledi set -a $ 1 komutunda tanımlanan dışa aktarma değişkenleri

Not; Noam'ın pythonu, ortamı çocuk sürecine “ihraç ettiği” için çalıştı.


1
2018-05-11 05:05





Cron işlerini elle çalıştırmanın bir yolunu bulamadım ama bu write-up, cronjob'in senaryoyu el ile çalıştırabileceği ve çalıştırdığı ortamın ayarlanmasını önerir.


0
2017-11-18 14:07



OP'nin nasıl yapılacağını bilmek istediğini yapma önerisi değil mi? - womble♦
Bu yüzden, nasıl yapılacağını açıklayan yazının bağlantısını dahil ettim. Burada her şeyi kopyalayıp yapıştırmanın gerekli olmadığını düşünmüştüm. - oneodd1