Hello I'am trying to execute a shell command in my php script but it is not working.
My php script :
//I save the Order
$holdedOrder->save();
$id = $holdedOrder->id;
$old_path = getcwd();
chdir(__DIR__.'/../');
$scriptFile = 'anacron_job_unhold_order.sh';
$bool = file_exists($scriptFile);
//$bool is true !
//this command works in shell but not in here do not know why
$s = shell_exec("echo \"/usr/bin/bash $scriptFile $id\" | /usr/bin/at now +$when");
chdir($old_path);
return [$s,$bool];
$when has a valid value 4 hours or 4 days ...
The command will be :
echo bash anacron_job_unhold_order.sh 29 | at now +1 minutes
the output is null. Trying it with exec() is returning 127 code
Edit :
I removed www-data from /etc/at.deny and still the same problem
The command shell_exec("echo \"/usr/bin/bash $scriptFile $id\" | /usr/bin/at now +$when"); is probably causing the issue, you should take a closer look on how at works.
The command should be something like
at [options] [job...]
To give a job to at from the command instead of STDIN, use heredoc syntax
at now + 1 minute <<< 'touch /tmp/test'
So the PHP code should be something like;
$s = shell_exec("/usr/bin/at now + {$when} <<< '/usr/bin/bash {$scriptFile} {$id}'");
exec($s, $output, $return_var);
Related
I'm trying to get the output of the following awk command via PHP but i get no output
$time_ref = date("Y-m-d\TH:i:s",strtotime(date('c', (time() - 80)))); //2020-03-29T21:00:30
$s_string = 'awk \'$0 > "'.$time_ref.'" && $0 ~ "AAA4311A01A404C4E21ABE55"\' /var/log/syslog | tail -1';
echo shell_exec($s_string);
Running the awk from console directly it works:
pi#raspberrypi:/var/log $ awk '$0 > "2020-03-30T10:06:28" && $0 ~ "AAA4311A01A404C4E21ABE55"' syslog
2020-03-30T10:07:40.300908+02:00 RadioBridge ESP-RSL: RESULT = {"RfRaw":{"Data":"AAA4311A01A404C4E21ABE55"}}
Any suggestion on why it does not work from PHP?
There are many solution.
1) if you run the PHP file in web, you should set the permission to the awk file.
2) we should set the path of the "awk"
$PATH = "real path";
putenv("PATH=$PATH");
$_string = "./awk ...."
Thanks.
First let's run the command via terminal:
$ echo 1; /etc/init.d/apache3 restart; echo 2;
result.. ( apache3 on purpose to see an error )
1
bash: /etc/init.d/apache3: No such file or directory
2
awsome.
now let's run this via php..
<?php
$command = "echo 1; /etc/init.d/apache3 restart; echo 2; 2>&1";
$response = shell_exec("$command");
echo $response;
?>
all I see on the browser is: 1 2
I tried all sorts of things. replaced the semi colons with "&&"..
tried all the php stuff such as..
passthru()
exec()
system()
popen()
i tried it all pretty much. been hours.. can not get it to show me the same stuff i see via terminal.
You have to use 2>&1 after the restart command
Your command :
$command = "echo 1; /etc/init.d/apache3 restart; echo 2; 2>&1";
yours has "2>&1" at the end which has no use.
Also you will add to 2>&1 after each command in case others uses STDERR
$command = "echo 1; /etc/init.d/apache3 restart 2>&1; echo 2 ";
Consider using exec. The basis function only returns the first line of the output:
$response = exec("$command"); // just the first line
But use the additional parameters to capture both the output (as an array) and the return value
$retval = NULL;
$output = NULL;
$response = shell_exec("$command", $output, $retval); // last two params are passed by reference and modified by the command
Also, as user993553 posted, the output captured by these cli functions in PHP will usually just return stdout and not stderr. You can append " 2>&1" to any given command (note the space before the 2) in order to route stderr into the output.
That said, your function becomes:
$command = "echo 1; /etc/init.d/apache3 restart 2>&1; echo 2;";
$retval = NULL;
$output = NULL;
$response = exec($command, $output, $retval);
var_dump($output);
and the output:
array(3) {
[0] =>
string(1) "1"
[1] =>
string(37) "sh: 1: /etc/init.d/apache3: not found"
[2] =>
string(1) "2"
}
EDIT: you can also check $retval for an error condition. If it's not empty or zero, then signifies an error.
From the manual of shell_exec:
ALSO, note that shell_exec() does not grab STDERR, so use "2>&1" to
redirect it to STDOUT and catch it.
I have a php page that creates a shell script that the same php page starts after creating it, inside I have one of many commands that I want to send the process to a log that does not work while others actually work....
<php
$scriptfile = script.sh;
$logfile = process.log;
$imgfile = image.ppm;
//this one works, it sends the output to the log file
$cmd ="Scripts/convert.sh file.doc > $logfile \\\n";
file_put_contents($scriptfile, $cmd, FILE_APPEND | LOCK_EX);
//this one does not work, it does not send the output to the log file and stops the process
$cmd = "&& for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page \$i; tesseract $imgfile-\$i.ppm $imgfile-\$i -l eng; done >> $logfile";
file_put_contents($scriptfile, $cmd, FILE_APPEND | LOCK_EX);
$cmd = "/bin/sh $scriptfile > /dev/null 2>&1 &";
shell_exec($cmd);
?>
I have tried the not working command from the shell and it does send the output to the log file, either this way:
for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i; tesseract image-$i.ppm image-\$i -l eng; done >> process.log
or this way:
for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i >> process.log; tesseract image-$i.ppm image-\$i -l eng; done
And here you have the way the shell script looks like after being created by php:
#! /bin/sh
Scripts/convert.sh file.doc >> process.log \
&& for i in $(seq --format=%003.f 0 $(( $(ls -1 | wc -l) -1 )) ); do echo doing OCR on page $i; tesseract image-000.ppm image-$i -l eng; done >> process.log
So my question is, what can be wrong, I've tried many different things already but no success unfortunately, any help or advice will be very welcomed!! thanks from now!!
I'm trying to ping a bunch of IPs using PHP/HTML.
<?php
$ip=array("192.10.1.1","192.10.1.2","192.10.1.3","192.10.1.4","192.10.1.5")
$list=count($ip);
$instruction = "";
for ($x=0; $x<$list; $x++)
{
if ($x > 0)
{
$send2_bg =" & ";
}
else
{
$send2_bg = "";
}
$instruction = $instruction.$send2_bg."ping -c 2 -w 1 ". $ip[$x]." | grep -i received | awk '{print $4}'" ;
}
echo $instruction;
$result =exec($instruction);
?>
Expected output array
1 1 0 0 2
But I'm failing to get the output, The instruction is constructed perfectly but after exec(), the output is not as I expect.
exec() just returns the last line of the output
shell_exec() returns all output
Try capturing the output like this:
exec($command, $host, $output);
print_r($output);
The problem is that you are echoing the instruction var see that link - PHP manual
Please reffer to the parameter output and echo that one instead the instruction var.
I'm trying to make a server manager and here is what I have so far:
<?php
$COMMAND = shell_exec('ps ax --format command | grep skulltag');
$arr = explode("./",$COMMAND);
$text = shell_exec('pgrep -u doom');
$arrtext = preg_split('/\s+/', $text);
for( $i = 1; $i < count($arr); $i++ ) {
echo $i,". PROCESS ID ",$arrtext[$i]," Command issued: ",$arr[$i];
echo '<br>';
}
?>
As you can see, I'm separating the $COMMAND string with ./ (file execution). However, for some reason at the end of the list there's this:
sh -c ps ax --format command | grep skulltag grep skulltag
Here is the full output for reference:
PROCESS ID 4793 Command issued: skulltag-server
PROCESS ID 4956 Command issued: skulltag-server -port 13000
PROCESS ID 4958 Command issued: skulltag-server -port 13001 sh -c
ps ax --format command | grep skulltag grep skulltag
What would be the easiest and most effective way to get rid of that line, and how would I do it? Thanks.
Change this:
ps ax --format command | grep skulltag
To this:
ps ax --format command | grep [s]kulltag
That way, the grep command itself contains the string '[s]kultag', which is not matched by the grep regular expression '[s]kultag'.
Also, two suggestions: 1. there's no guarantee that your initial ps | grep and your later pgrep will line up. Instead, use a single pgrep:
pgrep -afl skulltag
And 2. your for loop starts with 1, which will skip the process in arr[0].
Your php could be rewritten something like this:
$processes = explode("\n", shell_exec('pgrep -afl skulltag'));
foreach($processes as $i => $process) {
($pid, $command) = explode(' ',$process,2);
echo $i+1,". PROCESS ID ",$pid," Command issued: ",$command;
echo '<br>';
}
My quick and dirty solution is to append | grep -v grep to the command.