We've got a utility here that's using proc_open() to call ssh to run commands on a remote machine. However, in some cases we need to halt the command on the remote machine but proc_close() and proc_terminate() do not cause the desired signal to be sent through to the far side of the ssh connection. SSH will generally issue a SIGHUP to running programs when it is terminated, but we need to send a SIGINT to ssh which will forward it through to the program running on the remote end.
I've googled as much as I can, and there seem to be a number of pcntl functions for receiving signals, but I have not been able to find anything about sending signals via PHP, let alone anything related to proc_* functions.
You can sending signals via PHP :
posix_kill(posix_getpid(), SIGTERM);
Related
I have a long running PHP script that I'm attempting to convert into a systemd daemon.
While planing the daemon, I figured that I could simply send SITERM/SIGUSR1/SIGUSR2/etc. signals to restart/reload to my script when necessary using the kill command, but after reading through the systemd documentation, I've noticed this bit in the "ExecReload" section:
Note however that reloading a daemon by sending a signal (as with the example line above) is usually not a good choice, because this is an asynchronous operation and hence not suitable to order reloads of multiple services against each other. It is strongly recommended to set ExecReload= to a command that not only triggers a configuration reload of the daemon, but also synchronously waits for it to complete.
So, while my script will run just fine and the daemon itself will work properly using kill to signal various events (I don't have and most likely won't ever have another daemon that would depend on this one), the quote above got me thinking about alternatives of sending a synchronous message to the daemon.
The only thing that I could think of so far is:
Open a local socket in the daemon and listen for messages on it
Execute any supported action when receiving a message
Send an OK message back to the sender once the action is complete
Is there a better/recommended/optimal way of achieving this?
I have created a simple C daemon in Linux. The daemon is setup to catch the SIGTERM signal, do some cleanup and terminate. When run from the command line, this behaves as expected. Sending a SIGTERM to the daemon via the kill command gets handled properly.
I would however like to be able to start and stop the daemon from a PHP application. I do this using exec() in PHP. To start
exec("$daemon_name");
and to stop
exec("kill $daemon_pid");
Starting the daemon this way always works, but stopping doesn't. In fact, when started this way, executing kill from the command line also doesn't work. Only "kill -9" now works, and this obviously does not do the required cleanup. As far as I can tell, the process is simply not getting the signal.
Here is what really gets me. When I deploy this exact same configuration on SLES 12 or OpenSuSE 42.2, it doesn't work, but on OpenSuSE 42.1, it does work (I can start AND stop via PHP).
It is not a permissions issue, I verified this.
I'm out of ideas as to what can cause the process to not receive the SIGTERM signal. Looking at the output of "ps aux" and "ps -ef" I can see no difference between a daemon started from the command line, and one start via PHP.
Edit:
Thanks for all comments so far. None of them seems to take into account that the exact same code works on some systems, but not other. The only thing I can think of, is that the daemon is started in different environments. Question: Is there anything in the environment that a process is started in that can cause it to ignore signals?
Maybe your question should be why kill <pid> might not work. It is not a certain issue with PHP. kill can easily be ignored by the processes. Now you mention that it is a C daemon, however, you do not mention what the daemon does. So I will just assume that your daemon awaits for I/O, it is not properly configured with a timeout, and you kill it. Then the process will just won't be killed no matter what.
You can read here https://askubuntu.com/questions/59811/kill-pid-not-really-killing-the-process-why for possible solutions.
I have a processes that is open and can retrieve variables but it is running in the back ground.
so i need to send a variable to the processes using the PID ?? is it possible in the command line to send a variable to a processes or to reconnect to a processes.
Interprocess communication is often handled by sockets, which are supported in PHP. So if you have control over both applications you can set up sockets to communicate between them.
*nix type shells
You can reconnect to a process by doing fg [job id] (which isn't the PID but you can find it by using the jobs command from terminal)
IPC
You can also send variables into programs if the program is configured to accept it. It may read it off of a pipe, file, or network socket
A program is also able to receive signals (sent with the kill -[signal]) if its simply waiting for a boolean message
For php, sending variables through these methods may involve serialization of the variables prior to transmission
I'm planning the development of a server written in PHP that can service socket requests. I use a free host (Heliohost) for testing, and it has cPanel. So far the only thing I've been able to think of to have a PHP script always running is to write a cron job that runs a bash script to check ps to see if the PHP is already running, and if it isn't, start it.
Is there a better way? Perhaps a way for a PHP thread to be started on an HTTP request and continue to run in Apache after the request has been serviced?
You will almost certainly not have success running persistent processes from Apache. It is designed to prevent that scenario (though if you can get to the fork(2) system call, it is probably do-able). I wouldn't recommend trying it though.
What would make more sense is if you use a hosting provider that gives you the ability to write your own crontab(5) specifications and run the PHP interpreter directly. Then you could just add a line to your crontab(5) like:
#reboot /path/to/php /path/to/script.php
Your script should probably perform the usual daemonization tasks so that cron(8) isn't stuck waiting for your process to exit.
I'm trying to do a potentially long background process in response to an incoming AJAX request, but using nohup or setsid via shell_exec causes the server to fork bomb. We use suexec and FastCGI, and when it bombs it took the entire server to a crawl.
shell_exec("nohup /home/me/myscript.php");
The script doesn't do anything lengthy right now, just outputs to an non-existant file (which never happens, because it blows up first)
Thanks!
I've always seen the warnings at http://php.net/manual/en/intro.pcntl.php (although you're using nohup, I knoẁ) as a warning that forking from webserver processes is not a safe way to go. If a background process needs starting, I'll create a daemon / always running job process which can receive such requests (and hasn't got anything to do with the webserver), which forks/nohups at will.