PHP - Get amount of open files of current process - php

For monitoring purposes, I want to forward the amount of open files of the current process to our monitoring tool. In shell, the following command can be executed to get the desired information: ls /proc/PROCES_ID/fd | wc -l where PROCES_ID is the current process id. Is there a way to get this information natively in PHP?

To run any shell commands from within php script and get the output:
From PHP manual on exec() command
exec(string $command, array &$output = null, int &$result_code = null): string|false
For your command:
$output = []; // this array will hold whatever the output from the bash command
$result_code = null; // this will give you the result code returned, if needed
$command = '/proc/PROCES_ID/fd | wc -l'; // command to be run in the bash
exec($command, &$output, &$result_code);
//now you can look into $output array variable for the values returned from the above command
print_r($output);
But as mentioned in the comment, using bash script over php should be preferred if feasible.

Related

Laravel job dumps exec() error into command line instead of $output

I am trying to build a simple deployer in Laravel, that will receive a webhook, perform a deployment and store some information (from the hook) about said deployment.
I am using Laravel 5.2 jobs dispatcher to perform the following:
public function deploy()
{
$result = 0;
$output = array();
exec('cd ' . $this->deploymentMapping->full_file_path . '; git pull', $output, $result);
return array(
'result' => $result,
'output' => $this->outputToString($output)
);
}
My understanding of the exec() function is that this should not dump any errors directly, but will store them in $output.
However, when I run php artisan queue:work on my server in the command line, to test the job dispatcher, I just immediately get fatal: Not a git repository (or any of the parent directories): .git dumped into the command line output. This git error is correct, but it is making the job "fail" as though exec() threw an error. Is this correct? My job should be reporting the error in its own way, as follows:
public function handle()
{
$deploymentAttempt = new DeploymentAttempt();
$deploymentAttempt->deployment_id = $this->deploymentID;
$gitResponse = $this->deployer->deploy(); //the above function
$deploymentAttempt->success = !($gitResponse['result'] > 0);
$deploymentAttempt->message = $gitResponse['output'];
$deploymentAttempt->save();
}
This is because PHP's exec doesn't provide a simple way to capture the stderr output separately.
You need to capture the stderr too.
Redirecting stderr to stdout should do the trick. Append 2>&1 to the end of your command.
exec('cd ' . $this->deploymentMapping->full_file_path . '; git pull 2>&1', $output, $result);
It will fill the array $output with the expected output, one line per array key.
To know more about how 2>&1 works you can follow this thread.

php exec in the background with WAMP on Windows

with the following code i can call a php script and pass some variables into it
$cmd = 'php -f C:/wamp/www/np/myphpscript.php '.$var1;
exec($cmd);
this way my called script works, but , i need that process to be in the background , i dont want to wait for the script to finish, is there any way of doing that using wamp on windows ?
been doing some reading and some add a & at the end of the command, or a > NUL , now i noticed some of them are for linux , is there such a command for wamp on windows ? if there is please share it
EDIT: Due to the way the exec() command waits for the program to finish executing, it's very difficult to do this with vanilla exec(). I came across these solutions, and this one should work:
$rshell = new COM("WScript.Shell");
$rexec = $rshell->Run("php -f C:/wamp/www/np/myphpscript.php ".$var1, 0, false);
The WScript.Shell->Run command takes 3 arguments: the command (you can optionally add output redirection), window mode (0 = hidden), and wait it should wait to finish. Because the 3rd argument is false, this PHP should return immediately.
Original Solution: As this post suggests, you should try START /B cmd. It is virtually the Linux equivalent of cmd & in that it runs the command asynchronously, in the background, without user interaction or opening a new shell.
Because this will return immediately, PHP won't wait for it to finish, and the exec() command will not receive any output. Instead, try using shell output redirection. Your PHP given code would look like this:
$cmd = 'start /b "" php -f C:/wamp/www/np/myphpscript.php '.$var1.' >C:/wamp/www/np/output.txt';
exec($cmd);
Don't know what you are running and if you get a response to your command. But maybe it helps if you open a tab for each command. So you can see responses of each running script and at the end you can call javascript to close the tab.
You must set the variable php on windows environment !
If you have already done so skip the tutorials steps:
1. Open:
My Computer => Properties => Change Settings
2. Select the tab: Advanced
3. Click Environment Variables: Variable system
4. Click the button New
Add the name of the environment variable. Example = php
Add the path to executable php.exe. Example = D:\xampp\php\php.exe
Create a file myscript.php
The variariaveis $argc and $argv are native php.
You will notice that $ argc always carries the same value as the
result of calling count ($argv) in any case $argc is the standard
used and is a few milliseconds faster by being in memory (if that
makes any difference in performance your script).
//\n skip line
echo "\n\n";
//echo test debug
echo "Print Total Args : ";
//Print return variavel $argc
print_r($argc);
//\n skip line
echo "\n\n";
//echo test debug
echo "Print Array Args : \n\n";
//Print return variavel $argv
print_r($argv);
echo "\n";
// You can retrieve the arguments in the normal way.
$myvar_count = $argc;
$myvar_array_args = $argv;
Or if you want to set is not the environment variable, simply can call the path
Example: D:\xampp\php\php.exe myscript.php argument1 2 3 4 5
Retorn the Prompt in Windows
Total Args : 5
Array Args :
Array
(
[0] => test.php
[1] => argumento1
[2] => 2
[3] => 3
[4] => 4
)
I hope this helps! See you later!

Trying to get all the process table

I'm trying to print the whole process table with php (Actually I'm trying to print all the php processes that are running on my server). This is the code I'm using:
var_dump(exec("ps -A | grep php"));
When I start the php file, it returns me its own PID but not the others that are already running. I've checked through ssh console and there are 7, and that code prints me just 1 and completelly different to the others PID's.
Any solution?
Thanks in advance.
I found the answer at PHP Manual: getmypid
function countProcesses($scriptName)
{
// ps aux|grep "[u]pdate.php"|wc -l
$first = substr($scriptName, 0, 1);
$rest = substr($scriptName, 1);
$name = '"['.$first.']'.$rest.'"';
$cmd = "ps aux | grep $name | wc -l";
$result = exec($cmd);
return $result;
}
This function returns the number of processes are already running so I just call echo countProcesses('php6'); and it brings me back the amount of processes running as php6.

Starting shell process under www-data (apache2, php)

I need to start php process from shell on remove server with some arguments, so i thought that it should be a nice idea to make REST API, that executes some function when user performs GET request.
I wrote a simple bash script for testing and figured out that command-line argument is not being specified, when calling this script from website:
shell_exec('/var/www/test.sh 123')
Bash script source:
#!/bin/sh
echo $1;
When calling this bash script from root (or other existing user) it correctly shows argument it has received. When i call this script from website (that is running under user www-data under apache2), it returns nothing:
Also, if i execute this bash script in my console under www-data user, it also returns nothing:
su -c '/var/www/test.sh 123' www-data
Also i've tried to start process from different user from php (is supposed that this will not work for security reasons, but just in case):
$result = system("su -c '/var/www/test.sh 123' sexyuser", $data);
// var_dump($result): string(0) ""
// var_dump($data): int(1)
So, what privileges should i give to www-data user to run process under php?
You should let php run the script and handle the results
check php.net on exec for example http://www.php.net/manual/en/function.exec.php
//called by example.com/myshell.php?day=today&k=y&whatever=youwant
$arguments = implode(" ", $_GET);
$lastline_of_exec_result = exec ( "/your/command.sh ".$arguments); //sh called with today y youwant
echo $lastline_of_exec;
Where $arguments are the stringified list of ALL information your script got from GET arguments
if you want a ore precise in and output, try this:
//called by example.com/myshell.php?day=today&k=y&whatever=youwant
$argument = $_GET['whatever'];
$output = array();
$last_line = exec("your/command.sh ".$argument, &$output); //sh called with youwant
foreach($output as $line)
echo $line."<br/>".PHP_EOL;
or of course (with shell_exec)
$argument = $_GET['whatever'];
$output = shell_exec("your/command.sh ".$argument);
echo "<pre>".$output."</pre>";
make sure (shell_)exec is not listed under disable_functions in your php.ini

PHP exec() return value for background process (linux)

Using PHP on Linux, I'd like to determine whether a shell command run using exec() was successfully executed. I'm using the return_var parameter to check for a successful return value of 0. This works fine until I need to do the same thing for a process that has to run in the background. For example, in the following command $result returns 0:
exec('badcommand > /dev/null 2>&1 &', $output, $result);
I have put the redirect in there on purpose, I do not want to capture any output. I just want to know that the command was executed successfully. Is that possible to do?
Thanks, Brian
My guess is that what you are trying to do is not directly possible. By backgrounding the process, you are letting your PHP script continue (and potentially exit) before a result exists.
A work around is to have a second PHP (or Bash/etc) script that just does the command execution and writes the result to a temp file.
The main script would be something like:
$resultFile = '/tmp/result001';
touch($resultFile);
exec('php command_runner.php '.escapeshellarg($resultFile).' > /dev/null 2>&1 &');
// do other stuff...
// Sometime later when you want to check the result...
while (!strlen(file_get_contents($resultFile))) {
sleep(5);
}
$result = intval(file_get_contents($resultFile));
unlink($resultFile);
And the command_runner.php would look like:
$outputFile = $argv[0];
exec('badcommand > /dev/null 2>&1', $output, $result);
file_put_contents($outputFile, $result);
Its not pretty, and there is certainly room for adding robustness and handling concurrent executions, but the general idea should work.
Not using the exec() method. When you send a process to the background, it will return 0 to the exec call and php will continue execution, there's no way to retrieve the final result.
pcntl_fork() however will fork your application, so you can run exec() in the child process and leave it waiting until it finishes. Then exit() with the status the exec call returned.
In the parent process you can access that return code with pcntl_waitpid()
Just my 2 cents, how about using the || or && bash operator?
exec('ls && touch /tmp/res_ok || touch /tmp/res_bad');
And then check for file existence.

Categories