I'm setting a dashbord for manage a game server but I can not kill process with PID. I tried exec("kill $PID") exec("kill".$PID) posix_kill($PID, 15) but it did not work.
A posix_kill command give a "Operation not permitted" error yet the user apache is www-data and the user for the minecraft script is www-data also.
<?php
include('pidminecraft.php') ;
$output = shell_exec("bash /srv/scripts/pidphp.sh $PID ");
if ( $output == "run" )
{ exec('kill'. $PID); shell_exec("bash /srv/minecraft/minecraft_survie/start.sh >> /srv/web/minecraft/minecraft.txt 2>&1"); }
else
{ exec("bash /srv/minecraft/minecraft_survie/start.sh >> /srv/web/minecraft/minecraft.txt 2>&1"); }
?>
Related
I was trying to run a command from PHP to my Linux server but I'm having some trouble with one command:
This is the script:
<?php
$output=null;
$retval=null;
exec('speedtest -L -f, --format=json 2>&1', $output, $retval);
echo "Returned with status $retval and output:\n";
print_r($output);
?>
The output is:
Returned with status 134 and output:
Array ( [0] => terminate called after throwing an instance of 'std::logic_error'
[1] => what(): basic_string::_M_construct null not valid
[2] => Aborted (core dumped))
The user that runs the script is: www-data
if I try to run it directly on the terminal it works.
command from terminal: sudo -u www-data speedtest -L
output: {"type":"serverList","timestamp":"2021-02-23T09:20:51Z","servers":[{"id":4302,"name":"Vodafone IT","location":"Milan","country":"Italy","host":"speedtest.vodafone.it","port":8080},{"id":7839,"name":"Fastweb SpA","location":"Milan","country":"Italy","host":"spd-pub-mi-01-01.fastwebnet.it","port":8080},{"id":11427,"name":"EOLO","location":"Milan","country":"Italy","host":"test.eolo.it","port":8080},{"id":1434,"name":"CWNET","location":"Milan","country":"Italy","host":"speedtest.cheapnet.it","port":8080},{"id":3667,"name":"TIM SpA","location":"Milan","country":"Italy","host":"speedtestmi1.telecomitalia.it","port":8080},{"id":8211,"name":"CDLAN S.R.L.","location":"Milan","country":"Italy","host":"speedtest.cdlan.it","port":8080},{"id":11675,"name":"Italiaonline Supernap","location":"Milan","country":"Italy","host":"speedtest-supernap.italiaonline.it","port":8080},{"id":20551,"name":"Optima Italia","location":"Milan","country":"Italy","host":"mi-speedtest.optimaitalia.com","port":8080},{"id":26415,"name":"P-Lab","location":"Milan","country":"Italy","host":"speed.speedymilan.net","port":8080},{"id":19177,"name":"Seeweb","location":"Milan","country":"Italy","host":"ookla-mil.seeweb.it","port":8080}]}
If I run another command it works perfectly:
<?php
$output=null;
$retval=null;
exec('whoami', $output, $retval);
sleep(1);
echo "Returned with status $retval and output:\n";
print_r($output);
?>
The output is:
Returned with status 0 and output: Array ( [0] => www-data )
Do you guys have any suggestions?
I figured out a way to make it work but probably isn't the best one:
<?php
// attributes
private $output;
private $retval;
private $command;
// methods
function get_serverUpdates($user, $password) {
$command = 'echo '.$password.' | su -l '.$user.'-s /bin/bash -c "speedtest -L -f, --format=json" 2>&1';
$resl = exec($command, $output, $retval);
return json_decode(substr($resl, 10));
}
?>
It does return the correct information.
I think the problem was that as #MarkusZeller said that www-data doesn't have the permission to run all the programs installed.
I have a bit of code that runs on the remote server fine but will not run on my local php instance.
private function serverCmd($server, $cmd, $exec = false) {
$line = system("whoami");
print($line."\n");
$localCmd = 'ssh -o StrictHostKeyChecking=no myuser#uk-staging.internal.myhost.com "mkdir -p /home/deploy/backups/etl; rm -f /home/deploy/backups/etl/*.gz; rm -f /home/deploy/backups/etl/*.csv; sudo chown myhost:mysql /home/deploy/backups/etl"';
for ($retry = 0; $retry < 10; $retry++) {
if ($exec) {
$output = array();
exec($localCmd, $output, $retval);
if ($retval === 0) return $output;
}
else {
system($localCmd, $retval)
if ($retval === 0) return true;
}
sleep(1);
}
return false;
}
The issue is with the this line : system($localCmd, $retval).
if i run the ssh command directly on my ubuntu shell it works but if php trys to run it via that line it just hangs and I get the following error on the server its trying to ssh into :
sshd[10203]: Postponed keyboard-interactive for my user sshd[10202]: error: PAM: Authentication failure for myuser.
My dev machine has ssh keys setup to that I can just ssh in without entering a password. I assumed that php would use the same as its using my user.
How do I make sure php is using the same keys and authentication methods to ssh in as my shell? This is a cli script
Anybody got any ideas?
I am new to daemons and shell script.
I have followed a tutorial to run a PHP file as a service.
Here is the code. I did chmod a+x on both the /etc/init.d/daemon and the /home/user/Work/Daemon.php files.
Here is the code of the bash file daemon. The problem that I am facing is that, when I do a sudo service daemon start, it just prints Starting Program Name: and does not close it(i.e. I have to do a ctrl+c to close it). When I check the log that the PHP file it printing, it does show that the PHP file was running when the command was given.
#!/bin/bash
#
# /etc/init.d/Daemon
#
# Starts the at daemon
#
# chkconfig: 345 95 5
# description: Runs the demonstration daemon.
# processname: Daemon
# Source function library.
. /etc/init.d/functions
#startup values
log=/var/log/Daemon.log
#verify that the executable exists
test -x /home/user/Work/Daemon.php || exit 0RETVAL=0
#
# Set prog, proc and bin variables.
#
prog="Program Name"
proc=/var/lock/subsys/Daemon
bin=/home/user/Work/Daemon.php
start() {
# Check if Daemon is already running
if [ ! -f $proc ]; then
echo -n $"Starting $prog: "
daemon $bin --log=$log
RETVAL=$?
[ $RETVAL -eq 0 ] && touch $proc
echo
fi
return $RETVAL
}
stop() {
echo -n $"Stopping $prog: "
killproc $bin
RETVAL=$?
[ $RETVAL -eq 0 ] && rm -f $proc
echo
return $RETVAL
}
restart() {
stop
start
}
reload() {
restart
}
status_at() {
status $bin
}
case "$1" in
start)
start
;;
stop)
stop
;;
reload|restart)
restart
;;
condrestart)
if [ -f $proc ]; then
restart
fi
;;
status)
status_at
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
exit 1
esac
exit $?
exit $RETVAL
And here is the code of Daemon.php
#!/usr/bin/php
<?php
while(true){
file_put_contents('/var/log/Daemon.log', 'Running...', FILE_APPEND);
sleep(1);
}//end while
?>
UPDATE
I changed the PHP file to the following code, and it stared working. The daemon was expecting a return. But I don't understand why it goes to the main process block in PHP after the return. Could someone please explain it?
New Code.
#!/usr/bin/php
<?php
$log = '/var/log/vb_q.log';
//fork the process to work in a daemonized environment
file_put_contents($log, "Status: starting up.n", FILE_APPEND);
$pid = pcntl_fork();
if($pid == -1){
file_put_contents($log, "Error: could not daemonize process.n", FILE_APPEND);
return 1; //error
}
else if($pid){
return 0; //success
}
else{
//the main process
while(true){
file_put_contents($log, 'Running...', FILE_APPEND);
sleep(1);
}//end while
}//end if
?>
But I don't understand why it goes to the main process block in PHP
after the return. Could someone please explain it?
It does not go to the main process block after the return. The $pid = pcntl_fork() creates a child process; now there are two processes executing this same code:
the parent, where $pid is the ID of the child process, executes the block
else if($pid){
return 0; //success
}
and after the return the Daemon.php program terminates (which causes your shell script's start() function to resume)
the child, where $pid is 0, executes the block you call main process
else{
//the main process
while(true){
file_put_contents($log, 'Running...', FILE_APPEND);
sleep(1);
}//end while
}//end if
where it did not go after a return, but just thru the if … else.
It sounds like your bash script is running the php process alright, but it is running in the foreground and the bash script is waiting for it to end before it continues. Since the php script runs forever, try adding an ampersand after the command like this: daemon $bin --log=$log & to make your php process run in the background.
Try adding a running user to your daemon so that it runs with appropriate privileges instead of root.
Additionally move your touch $proc above the daemon start. To ensure it is able to create the lock file prior to starting the daemon.
The stop command looks identical to mine.
eg:
start(){
if [ ! -f $proc ]; then
echo -n "Starting $prog: "
touch $proc
daemon --user=apache --log=$log $bin
RETVAL=$?
[ $RETVAL -ne 0 ] && rm $proc
echo
else
echo -n "$prog is already running"
echo
fi
return $RETVAL
}
Also you can test your lock file to ensure you are able to access it.
. /etc/init.d/functions
#startup values
log=/var/log/Daemon.log
prog="Program Name"
proc=/var/lock/subsys/Daemon
bin=/home/user/Work/Daemon.php
if [ ! -w /var/lock/subsys ]; then
echo -n "You do not have permissions to run this service"
echo
exit 0
fi
if [ ! -x $bin ]; then
echo $bin is not executable!
echo
exit 0
fi
RETVAL=0
Update
PHP scripts are not meant to run as a normal service.
In order to control it you have to fork it for the service to continue running and allow the parent PHP process to close the script, rather than in the current thread that called it. See: http://man7.org/linux/man-pages/man3/daemon.3.html#RETURN_VALUE
For example launch a service - service never returned that it started or errored, since it is in a while loop.
You should additionally check for your child process and ensure it is assigned as a main process (session leader), after it has been forked as well. Otherwise the calling process remains the leader.
if ($pid == -1) {
return 1; //return error to service
} elseif ($pid) {
//parent process - break out of it
return 0;
} else {
/* child Process - run by calling pcntl_fork */
try {
if (posix_setsid() < 0) {
return; //error assigning a session id
}
$sid = posix_getpid(); //retrieve current process name
//... Your Code Here
} catch(\Exception $e) {
return 1;
}
}
See: http://linux.die.net/man/2/setsid
I'm working on a shell in php, and I want to display the same output as bash. When in bash you execute sleep 10 & you'll get [1] <PID>. How can I do the same in php, when I call shell using:
if (preg_match("/&\s*$/", $command)) {
$this->$shell_fn($token, '/bin/bash -c ' . escapeshellarg($command) .
" > /dev/null");
return array(
'output' => '',
'cwd' => $path
);
}
$shell_fn is variable that point to wrapper over shell_exec, exec or cgi script called by curl. Is it even possible to get the pid from php or using a shell?
If you want the pid in bash, you can do use the ! special parameter to get the pid of the most recently backgrounded process:
bash -c 'sleep 10 & echo $!'
I don't know exactly how php spawns external processes, but I imagine you'd be able to capture the echo output here, just by running the above shell command.
I use this functions to manage process:
function ProcessStart($cmdline) // return pid
{
exec( "nohup $cmdline >/dev/null 2>&1 & echo $!", $output) ;
// print_r ($output);
return (int)$output[0];
}
function ProcessStatus($pid) // return TRUE (live) o FALSE (dead)
{
exec("ps -p $pid",$output);
// print_r($output);
return ( isset($output[1]) ? TRUE : FALSE ) ;
}
function ProcessStop($pid)
{
exec("kill $pid",$output); // kill -9 ??
}
Could anyone explain me how to retrieve the ProcessID from a Process which is started with ssh2_exec? I've tried many things, but its only giving the following message "Resource id #6"
Below is the code where I am struggling with But instead of echo'ing the ProcessID I only get "Resource id #6"
$pid = ssh2_exec($connection, 'cd /home/servers/; nohup ./sc_serv' .$config .' & > /dev/null 2>&1 & echo $!');
This will help you to find the process id
<?php
//this will return the process id
$pid = getmypid();
//you can check the process id
if(file_exists('/proc/'.$pid))
{
echo 'The process is still running.';
}
I think it should be:
$pid = ssh2_exec($connection, 'cd /home/servers/; nohup ./sc_serv' .$config .' & > /dev/null 2>&1; echo $!');
To get the process id of the process started on the remote machine by ssh2_exec, you can do:
$cmd = "cd /home/servers/; nohup ./sc_serv' .$config .' & > /dev/null 2>&1 & echo $!"
$stdout_stream = ssh2_exec($connection, $cmd);
$dio_stream = ssh2_fetch_stream($stream, SSH2_STREAM_STDIO);
stream_set_blocking($dio_stream, true);
$pid = stream_get_contents($dio_stream);