Hola muchachos... le cuento que tengo una pequeña duda... tengo un Servidor con Ubuntu y PHP 5.6.3 y me gustaría invocar desde PHP a un programa que corre "en modo terminal" y que en algún otro momento pueda enviarle la orden de finalizar el programa...
por si no me explique bien... lo que me gustaría hacer es llamar a que se ejecute un programa desde php, y desde php mas adelante poder enviarle instrucciones al programa... como por ejemplo "stop" y la verdad es que no tengo idea de por donde empezar...
si no fui claro con lo que dije intentare explicarlo de nuevo.
Gracias
Saludos.
¿Enviar instrucciones? ¿El programa funciona de forma interactiva? Puedes usar 'kill' con shell_exec para matar el proceso.
Claro. por ejemplo es como el servicio de apache. "apache start", "apache restart" "apache stop"... eso me gustaría poder "controlar"
Cita de: agus0 en 17 Marzo 2015, 16:04 PM
Claro. por ejemplo es como el servicio de apache. "apache start", "apache restart" "apache stop"... eso me gustaría poder "controlar"
¿Tienes otro servidor web que esta usando PHP para iniciar el proceso de apache? Ese servidor web debe tener permisos de root para poder iniciar apache al menos bajo el puerto 80. Si es el mismo servidor apache que esta corriendo bajo el mismo puerto solo podrias usar apache stop y para eso tambien necesitas permisos root.
Di apache como ejemplo pero es otro programa, el problema y la diferencia con apache es que usando shel_exec() es como si se cerrara "terminal" en la que estoy ejecutando el programa
Cita de: agus0 en 17 Marzo 2015, 16:24 PM
Di apache como ejemplo pero es otro programa, el problema y la diferencia con apache es que usando shel_exec() es como si se cerrara "terminal" en la que estoy ejecutando el programa
¿Cerrara "terminal"?
Si es un script que solo inicia y detiene un programa en el background entonces con shell_exec te basta. Si es un proceso que continua ejecutandose y no regresa un valor necesitas enviarlo al background:
shell_exec(.'/server &>/dev/null &')
Cita de: MinusFour en 17 Marzo 2015, 16:34 PM
¿Cerrara "terminal"?
Si es un script que solo inicia y detiene un programa en el background entonces con shell_exec te basta. Si es un proceso que continua ejecutandose y no regresa un valor necesitas enviarlo al background:
shell_exec(.'/server &>/dev/null &')
A lo que me refiero con "Cerrar el terminal" es que, la funcion de php "shell_exec()" se comporta como si cada vez que se termina la instrucción la terminal se finalizara (exit), es decir si yo uso
<?php
shel_exec('cd /home/unacarpeta');
echo(shel_exec('ls'));
?>
esto no me muestra el contenido de la carpeta "/home/unacarpeta" sino que muestra el contenido de la carpeta donde se encuentre el archivo php que invoca la función shel_exec(), ahora para motrar el contenido en "/home/unacarpeta" yo tendría que hacer todo en una misma linea usando "&&"
se me ocurrió un ejemplo mas concreto que es casi justo lo que busco...
ejemplo tengo en mi servidor el servicio de "Minecraft" y para iniciarlo tengo que ejecutar el programa Java
java -Xmx2048M -Xms1024M -jar server_minecraft.jar nogui
ahora bien, como puedo invocar a este programa y que no se cierre desde php y en el caso de que mas adelante lo quiera cerrar enviándole la instrucción "stop" como podría hacerlo.
Saludos
Mod: No hacer doble post.
Cita de: agus0 en 18 Marzo 2015, 12:54 PM
A lo que me refiero con "Cerrar el terminal" es que, la funcion de php "shell_exec()" se comporta como si cada vez que se termina la instrucción la terminal se finalizara (exit), es decir si yo uso
<?php
shel_exec('cd /home/unacarpeta');
echo(shel_exec('ls'));
?>
esto no me muestra el contenido de la carpeta "/home/unacarpeta" sino que muestra el contenido de la carpeta donde se encuentre el archivo php que invoca la función shel_exec(), ahora para motrar el contenido en "/home/unacarpeta" yo tendría que hacer todo en una misma linea usando "&&"
se me ocurrió un ejemplo mas concreto que es casi justo lo que busco...
ejemplo tengo en mi servidor el servicio de "Minecraft" y para iniciarlo tengo que ejecutar el programa Java
java -Xmx2048M -Xms1024M -jar server_minecraft.jar nogui
ahora bien, como puedo invocar a este programa y que no se cierre desde php y en el caso de que mas adelante lo quiera cerrar enviándole la instrucción "stop" como podría hacerlo.
Saludos
Mod: No hacer doble post.
No necesitas hacer un cambio de directorio para usar ls.
ls /home/unacarpeta
En cuanto a tu server de Minecraft, si al iniciar el server no retorna un valor y sigue corriendo el proceso en el foreground tu shell exec se queda colgado, porque sigue esperando una respuesta del comando. Es por eso que tienes que enviarlo al background.
En cuanto a enviar "stop" no se que comando utilices para eso.
Cita de: MinusFour en 18 Marzo 2015, 16:44 PM
No necesitas hacer un cambio de directorio para usar ls.
ls /home/unacarpeta
En cuanto a tu server de Minecraft, si al iniciar el server no retorna un valor y sigue corriendo el proceso en el foreground tu shell exec se queda colgado, porque sigue esperando una respuesta del comando. Es por eso que tienes que enviarlo al background.
En cuanto a enviar "stop" no se que comando utilices para eso.
si lo de hacerlo en una sola linea lo se, pero lo di a modo de ejemplo...
En el caso del Servidor. tendria que "retomar" esa aplicación que quedo BackGround y enviar la instrucción "stop" ¿es esto posible?
Cita de: MinusFour en 17 Marzo 2015, 16:34 PM
¿Cerrara "terminal"?
Si es un script que solo inicia y detiene un programa en el background entonces con shell_exec te basta. Si es un proceso que continua ejecutandose y no regresa un valor necesitas enviarlo al background:
shell_exec(.'/server &>/dev/null &')
otra cosa y perdón por la ignorancia pero me explicas un poco mas...
Para que sirve el "." antes del apostrofo, y para que es el "&>" y el "&" del final. Gracias!
Mod: No hacer doble post.
Cita de: agus0 en 18 Marzo 2015, 16:47 PM
si lo de hacerlo en una sola linea lo se, pero lo di a modo de ejemplo...
En el caso del Servidor. tendria que "retomar" esa aplicación que quedo BackGround y enviar la instrucción "stop" ¿es esto posible?
shell_exec() no es una terminal interactiva. Si por ejemplo, el programa espera que escribas en la terminal: "stop", no lo vas a poder hacer atraves de shell_exec(). Lo que si puedes hacer es enviar la señal SIGTERM a tu proceso de java por medio de kill. En ese caso no importa si esta en el foreground o background, la aplicacion termina.
Esto te ayudará.
<?php
/* An easy way to keep in track of external processes.
* Ever wanted to execute a process in php, but you still wanted to have somewhat controll of the process ? Well.. This is a way of doing it.
* @compability: Linux only. (Windows does not work).
* @author: Peec
*/
class Proceso{
private $pid;
private $command;
public function __construct($cl=false){
if ($cl != false){
$this->command = $cl;
$this->runCom();
}
}
private function runCom(){
$command = 'nohup '.$this->command.' > /dev/null 2>&1 & echo $!';
exec($command ,$op);
$this->pid = (int)$op[0];
}
public function setPid($pid){
$this->pid = $pid;
}
public function getPid(){
return $this->pid;
}
public function status(){
$command = 'ps -p '.$this->pid;
exec($command,$op);
if (!isset($op[1]))return false;
else return true;
}
public function start(){
if ($this->command != '')$this->runCom();
else return true;
}
public function stop(){
$command = 'kill '.$this->pid;
exec($command);
if ($this->status() == false)return true;
else return false;
}
}
?>
ejemplo de prueba
$programa = "/usr/bin/perl script.pl parametros";
$proceso = new Proceso($programa);
Esperar a que termine por si solo
//proceso ejecutando
while($proceso->status()){
}
//proceso finalizado.
Puedes pararlo con los metodos de la clase, saludos.
Cita de: DonVidela en 19 Marzo 2015, 14:31 PM
Esto te ayudará.
Muchas Gracias... pero no entendí bien como usar esta Clase
Cita de: agus0 en 24 Marzo 2015, 16:30 PM
Muchas Gracias... pero no entendí bien como usar esta Clase
Solo es cuestion de pasarle el comando al constructor y de ahi iniciar o detener el proceso. Sin embargo, la clase de la forma en la que esta escrita, no puede detener el proceso entre peticiones. Tendrias que persistir la ID del proceso de alguna forma. Realmente la idea es la misma que comentaba, necesitas usar kill para enviar SIGTERM a tu proceso corriendo.
Cita de: MinusFour en 24 Marzo 2015, 16:56 PM
Solo es cuestion de pasarle el comando al constructor y de ahi iniciar o detener el proceso. Sin embargo, la clase de la forma en la que esta escrita, no puede detener el proceso entre peticiones. Tendrias que persistir la ID del proceso de alguna forma. Realmente la idea es la misma que comentaba, necesitas usar kill para enviar SIGTERM a tu proceso corriendo.
No sería buena idea mantener identificada por session la ID del proceso y matarla cuando el quiera? Es cosa de modificar la clase.
Yo preferiria guardar el proceso en una base de datos o un archivo. Pierdes mucho control sobre la PID si usas sessiones, porque las sessiones pueden expirar, son diferentes para cada usuario/navegador, etc.
Cita de: MinusFour en 24 Marzo 2015, 17:30 PM
Yo preferiria guardar el proceso en una base de datos o un archivo. Pierdes mucho control sobre la PID si usas sessiones, porque las sessiones pueden expirar, son diferentes para cada usuario/navegador, etc.
Todo depende de lo que el necesite hacer exactamente.