Pertanyaan Jalankan skrip php sebagai proses daemon


Saya harus menjalankan skrip php sebagai proses daemon (tunggu instruksi dan lakukan hal-hal). Pekerjaan cron tidak akan melakukannya untuk saya karena tindakan harus diambil segera setelah instruksi tiba. Saya tahu PHP bukanlah pilihan terbaik untuk proses daemon karena masalah manajemen memori, tetapi karena berbagai alasan saya harus menggunakan PHP dalam kasus ini. Saya menemukan alat oleh libslack disebut Daemon (http://libslack.org/daemon) tampaknya membantu saya mengelola proses daemon, tetapi belum ada pembaruan dalam 5 tahun terakhir, jadi saya ingin tahu apakah Anda mengetahui beberapa alternatif lain yang sesuai untuk kasus saya. Setiap informasi akan sangat dihargai.


133
2018-01-10 10:06


asal


Jawaban:


Anda dapat memulai skrip php Anda dari baris perintah (yaitu bash) dengan menggunakan

nohup php myscript.php & 

itu & menempatkan proses Anda di latar belakang.

Edit:
Ya, ada beberapa kelemahan, tetapi tidak mungkin dikendalikan? Itu salah.
Sederhana kill processid akan menghentikannya. Dan itu masih merupakan solusi terbaik dan paling sederhana.


149
2018-01-10 10:46



Pilihan lainnya adalah menggunakan Baru mulai. Ini pada awalnya dikembangkan untuk Ubuntu (dan dikemas dengan standar), tetapi dimaksudkan agar cocok untuk semua distro Linux.

Pendekatan ini mirip dengan Supervisord dan daemontools, dalam hal ini secara otomatis memulai daemon pada sistem boot dan respawn pada penyelesaian skrip.

Cara mengaturnya:

Buat file skrip baru di /etc/init/myphpworker.conf. Berikut ini contohnya:

# Info
description "My PHP Worker"
author      "Jonathan"

# Events
start on startup
stop on shutdown

# Automatically respawn
respawn
respawn limit 20 5

# Run the script!
# Note, in this example, if your PHP script returns
# the string "ERROR", the daemon will stop itself.
script
    [ $(exec /usr/bin/php -f /path/to/your/script.php) = 'ERROR' ] && ( stop; exit 1; )
end script

Memulai & menghentikan daemon Anda:

sudo service myphpworker start
sudo service myphpworker stop

Periksa apakah daemon Anda berjalan:

sudo service myphpworker status

Terima kasih

Terima kasih banyak untuk Kevin van Zonneveld, di mana saya belajar teknik ini dari.


143
2018-05-16 01:54



Jika Anda bisa - ambil salinannya Pemrograman Lanjut di Lingkungan UNIX. Seluruh bab 13 dikhususkan untuk pemrograman daemon. Contohnya dalam C, tetapi semua fungsi yang Anda butuhkan memiliki pembungkus di PHP (pada dasarnya pcntl dan posix ekstensi).

Dalam beberapa kata - menulis daemon (ini hanya dapat dilakukan di OS berbasis OS nix - Windows menggunakan layanan) seperti ini:

  1. Panggilan umask(0) untuk mencegah masalah izin.
  2. fork() dan biarkan orang tua keluar.
  3. Panggilan setsid().
  4. Pengaturan pemrosesan sinyal SIGHUP (Biasanya ini diabaikan atau digunakan untuk memberi sinyal pada daemon untuk memuat kembali konfigurasinya) dan SIGTERM (untuk memberi tahu proses untuk keluar dengan lancar).
  5. fork() lagi dan biarkan orang tua keluar.
  6. Ubah direktori kerja saat ini dengan chdir().
  7. fclose()  stdin, stdout dan stderr dan jangan menulis kepada mereka. Cara yang tepat adalah dengan mengalihkannya ke salah satunya /dev/null atau file, tetapi saya tidak dapat menemukan cara untuk melakukannya dalam PHP. Hal ini dimungkinkan ketika Anda meluncurkan daemon untuk mengarahkan mereka menggunakan shell (Anda harus mencari tahu sendiri bagaimana melakukan itu, saya tidak tahu :).
  8. Lakukan pekerjaanmu!

Juga, karena Anda menggunakan PHP, berhati-hatilah untuk referensi siklik, karena pengumpul sampah PHP, sebelum PHP 5.3, tidak memiliki cara mengumpulkan referensi dan proses akan kebocoran memori, sampai akhirnya crash.


44
2018-01-10 11:24



Dengan yang baru systemd Anda dapat membuat layanan (pada Linux berbasis rhel).

Anda harus membuat file atau a symlink di /etc/systemd/system/, misalnya. myphpdaemon.service dan tempatkan konten seperti ini, myphpdaemon akan menjadi nama layanan:

[Unit]
Description=My PHP Daemon Service
#Requires=mysqld.service memcached.service #May your script needs mysql or other services to run.
#After=mysqld.service memcached.service

[Service]
User=root
Type=simple
TimeoutSec=0
PIDFile=/var/run/myphpdaemon.pid
ExecStart=/usr/bin/php -f /srv/www/myphpdaemon.php arg1 arg2> /dev/null 2>/dev/null
#ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command
#ExecReload=/bin/kill -HUP $MAINPID
KillMode=process

Restart=on-failure
RestartSec=42s

StandardOutput=null #If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one.
StandardError=/var/log/myphpdaemon.log
[Install]
WantedBy=default.target

Anda akan dapat memulai, mendapatkan status, memulai ulang dan menghentikan layanan menggunakan perintah

systemctl <start|status|restart|stop|enable> myphpdaemon 

Skrip PHP harus memiliki semacam "loop" untuk terus berjalan.

<?php
gc_enable();//
while (!connection_aborted() || PHP_SAPI == "cli") {

  //Code Logic

  //sleep and usleep could be useful
    if (PHP_SAPI == "cli") {
        if (rand(5, 100) % 5 == 0) {
            gc_collect_cycles(); //Forces collection of any existing garbage cycles
        }
    }
}

Contoh kerja:

[Unit]
Description=PHP APP Sync Service
Requires=mysqld.service memcached.service
After=mysqld.service memcached.service

[Service]
User=root
Type=simple
TimeoutSec=0
#Restart=on-failure
#RestartPreventExitStatus=1
#PrivateTmp=false
PIDFile=/var/run/php_app_sync.pid
ExecStart=/bin/sh -c '/usr/bin/php -f /var/www/app/private/server/cron/app_sync.php  2>&1 > /var/log/app_sync.log'
KillMode=process

Restart=on-failure
RestartSec=42s

[Install]
WantedBy=default.target

Catatan: Setiap kali Anda mengubah "myphpdaemon.service" Anda harus   jalankan `systemctl daemon-reload ', tetapi jangan khawatir jika Anda tidak melakukannya, itu akan terjadi   diminta kapan dibutuhkan.


32
2018-06-07 18:35



Saya menjalankan sejumlah besar daemon PHP.

Saya setuju dengan Anda bahwa PHP bukan bahasa terbaik (atau bahkan bagus) untuk melakukan hal ini, tetapi daemon berbagi kode dengan komponen yang menghadap ke web sehingga secara keseluruhan itu adalah solusi yang baik bagi kita.

Kami menggunakan daemontools untuk ini. Ini pintar, bersih dan dapat diandalkan. Sebenarnya kami menggunakannya untuk menjalankan semua daemon kami.

Anda dapat memeriksanya di http://cr.yp.to/daemontools.html.

EDIT: Daftar singkat fitur.

  • Secara otomatis memulai daemon saat reboot
  • Secara otomatis restart dameon pada kegagalan
  • Penebangan ditangani untuk Anda, termasuk rollover dan pemangkasan
  • Antarmuka manajemen: 'svc' dan 'svstat'
  • UNIX ramah (bukan nilai tambah untuk semua orang mungkin)

23
2018-01-19 05:32



Kamu bisa

  1. Menggunakan nohup seperti disarankan Henrik.
  2. Menggunakan screen dan jalankan program PHP Anda sebagai proses reguler di dalamnya. Ini memberi Anda kontrol lebih dari menggunakan nohup.
  3. Gunakan daemoniser seperti http://supervisord.org/ (Ini ditulis dengan Python tetapi bisa daemonise setiap program baris perintah dan memberi Anda remote control untuk mengelolanya).
  4. Tuliskan wrapper daemonise Anda sendiri seperti yang disarankan Emil tetapi itu terlalu berlebihan IMO.

Saya akan merekomendasikan metode paling sederhana (layar menurut saya) dan kemudian jika Anda ingin lebih banyak fitur atau fungsi, pindah ke metode yang lebih kompleks.


14
2018-01-19 07:09



Ada lebih dari satu cara untuk memecahkan masalah ini.

Saya tidak tahu secara spesifik tetapi mungkin ada cara lain untuk memicu proses PHP. Sebagai contoh jika Anda memerlukan kode untuk menjalankan berdasarkan peristiwa dalam database SQL Anda bisa menyiapkan pemicu untuk menjalankan skrip Anda. Ini sangat mudah dilakukan di bawah PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .

Jujur saya pikir taruhan terbaik Anda adalah membuat proses Damon menggunakan nohup. nohup memungkinkan perintah untuk terus dijalankan bahkan setelah pengguna logout:

nohup php myscript.php &

Namun ada masalah yang sangat serius. Seperti yang Anda katakan manajer memori PHP adalah sampah lengkap, itu dibangun dengan asumsi bahwa skrip hanya mengeksekusi selama beberapa detik dan kemudian ada. Skrip PHP Anda akan mulai menggunakan GIGABYTES memori setelah hanya beberapa hari. Anda HARUS JUGA membuat skrip cron yang berjalan setiap 12 atau mungkin 24 jam yang membunuh dan re-spawn skrip php Anda seperti ini:

killall -3 php
nohup php myscript.php &

Tetapi bagaimana jika skrip berada di tengah pekerjaan? Yah membunuh -3 adalah interupsi, sama seperti melakukan ctrl + c pada CLI. Script php Anda dapat menangkap interupsi ini dan keluar dengan lancar menggunakan pustaka PHP pcntl: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php

Berikut ini contohnya:

function clean_up() {
  GLOBAL $lock;
  mysql_close();
  fclose($lock)
  exit();
}
pcntl_signal(SIGINT, 'clean_up');

Ide dibalik $ lock adalah skrip PHP dapat membuka file dengan fopen ("file", "w") ;. Hanya satu proses yang dapat memiliki kunci tulis pada file, jadi dengan menggunakan ini Anda dapat memastikan bahwa hanya satu salinan skrip PHP Anda yang berjalan.

Semoga berhasil!


11
2018-01-18 22:57



Kevin van Zonneveld menulis artikel rinci yang sangat bagus tentang ini, dalam teladannya dia memanfaatkan System_Daemon Paket PEAR (tanggal rilis terakhir pada 2009-09-02).


10
2018-01-15 15:19