I am wanting to call a php file using exec.
When I call it I want to be able to pass a variable through (an id).
I can call echo exec("php /var/www/unity/src/emailer.php"); fine, but the moment I add anything like echo exec("php /var/www/unity/src/emailer.php?id=123"); the exec call fails.
How can I do this?
Your call is failing because you're using a web-style syntax (?parameter=value) with a command-line invokation. I understand what you're thinking, but it simply doesn't work.
You'll want to use $argv instead. See the PHP manual.
To see this in action, write this one-liner to a file:
<?php print_r($argv); ?>
Then invoke it from the command-line with arguments:
php -f /path/to/the/file.php firstparam secondparam
You'll see that $argv contains the name of the script itself as element zero, followed by whatever other parameters you passed in.
try echo exec("php /var/www/unity/src/emailer.php 123"); in your script then read in the commandline parameters.
If you want to pass a GET parameter to it, then it's mandatory to provide a php-cgi binary for invocation:
exec("QUERY_STRING=id=123 php-cgi /var/www/emailer.php");
But this might require more fake CGI environment variables. Hencewhy it is often advisable to rewrite the called script and let it take normal commandline arguments and read them via $_SERVER["argv"].
(You could likewise just fake the php-cgi behaviour with a normal php interpreter and above example by adding parse_str($_SERVER["QUERY_STRING"], $_GET); on top of your script.)
this adapted script shows 2 ways of passing parameters to a php script from a php exec command:
CALLING SCRIPT
<?php
$fileName = '/var/www/ztest/helloworld.php 12';
$options = 'target=13';
exec ("/usr/bin/php -f {$fileName} {$options} > /var/www/ztest/log01.txt 2>&1 &");
echo "ended the calling script";
?>
CALLED SCRIPT
<?php
echo "argv params: ";
print_r($argv);
if ($argv[1]) {echo "got the size right, wilbur! argv element 1: ".$argv[1];}
?>
dont forget to verify execution permissions and to create a log01.txt file with write permissions (your apache user will usually be www-data).
RESULT
argv params: Array
(
[0] => /var/www/ztest/helloworld.php
[1] => 12
[2] => target=13
)
got the size right, wilburargv element 1: 12
choose whatever solution you prefer for passing your parameters, all you need to do is access the argv array and retrieve them in the order that they are passed (file name is the 0 element).
tks #hakre
I know this is an old thread but it helped me solve a problem so I want to offer an expanded solution. I have a php program that is normally called through the web interface and takes a long list of parameters. I wanted to run it in the background with a cron job using shell_exec() and pass a long list of parameters to it. The parameter values change on each run.
Here is my solution: In the calling program I pass a string of parameters that look just like the string a web call would send after the ?. example: sky=blue&roses=red&sun=bright etc. In the called program I check for the existence of $argv[1] and if found I parse the string into the $_GET array. From that point forward the program reads in the parameters just as if they were passed from a web call.
Calling program code:
$pars = escapeshellarg($pars); // must use escapeshellarg()
$output = shell_exec($php_path . ' path/called_program.php ' . $pars); // $pars is the parameter string
Called program code inserted before the $_GET parameters are read:
if(isset($argv[1])){ // if being called from the shell build a $_GET array from the string passed as $argv[1]
$args = explode('&', $argv[1]); // explode the string into an array of Type=Value elements
foreach($args as $arg){
$TV = explode('=', $arg); // now explode each Type and Value into a 2 element array
$_GET[$TV[0]] = $TV[1]; // set the indexes in the $_GET array
}
}
//------------------------
// from this point on the program processes the $_GET array normally just as if it were passed from a web call.
Works great and requires minimal changes to the called program. Hope someone finds it of value.
Related
When I use web browser I pass parameters by this way:
http://localhost/script.php?nr=444524
and get it this way:
$var = $_GET('nr');
print_r($var);
but how to achieve the same result (pass and get parameters) when I compile same script with cmd on windows?
c:\php.exe script.php ?nr=444524
this way doesn't work
It doesn't work that way. $_GET is a variable created to feed in data from an HTTP request.
On the command line you enter arguments as:
php script.php 444524
From here you can ready the arguments as print_r($argv);.
All the words you put into the command line, starting with the script name can be found in the global variable $argv. Launch your script with various parameters and check the output of print_r($argv); to see what you get.
Check the documentation here
we have many php scripts running on live servers which use arguments from command line.
Now i need to add one more argument in some of these crons which will tell me about the environment, which in turn select the server (slave, master). ANd this selection of servers is a central library code.
I dont want to change argument accessed in current scripts.
so only option is to add this new environment argument at the end. But in that case there are crons which wont be containing this environment arguments. So i cannot blindly access the last argument in the library.
So i thought to use options for this.
so my script will be run in terminal like
php myscript.php arg1 arg2 -env slave
but in this case i cannot get options in php .May be because it mix of arguments supplied directly and with options..
what to do? Any help?
First search for the option(-env) in the array of argv get the key from array($argv) and increment by 1 to get the value of the option:
if (false !== $key = array_search('-env', $argv)) {
$value = $key+1;
$env = $argv[$value]; // $env will be 'slave' now.
} else {
// do something else
}
There might be some better options.
referred PHP if in_array() how to get the key as well? hehe!
Try moving options before the arguments when invoking the script.
php myscript.php -e slave arg1 arg2
or
php myscript.php --env slave arg1 arg2
Note: This will change the $argv array as the option and its value will show up first in $argv array and move other arguments to higher index.
I have created a crontab rule:
* * * * * php /my/directory/file.php
I want to pass a variable to be used in the file.php from this crontab.
What is the best method to do this?
Bear in mind that running PHP from the shell is completely different from running it in a web server environment. If you haven't done command-line programming before, you may run into some surprises.
That said, the usual way to pass information into a command is by putting it on the command line. If you do this:
php /my/directory/file.php "some value" "some other value"
Then inside your script, $argv[1] will be set to "some value" and $argv[2] will be set to "some other value". ($argv[0] will be set to "/my/directory/file.php").
When you execute a PHP script from command line, you can access the variable count from $argc and the actual values in the array $argv. A simple example.
Consider test.php
<?php
printf("%d arguments given:\n", $argc);
print_r($argv);
Executing this using php test.php a b c:
4 arguments given:
Array
(
[0] => test.php
[1] => a
[2] => b
[3] => c
)
May I add to the $argv answers that for more sophisticated command-line parameters handling you might want to use getopt() : http://www.php.net/manual/en/function.getopt.php
Neither of the above methods worked for me. I run cron on my hoster's shared server. The cron task is created with the cPanel-like interface. The command line calls PHP passing it the script name and a couple arguments.
That is how the command line for cron looks:
php7.2 /server/path/to/my/script/my-script.php "test.tst" "folder=0"
Neither of the answers above with $argv worked for my case.
The issue was noone told you have to declare $argv as global before you get the access to the CLI arguments. This is neither mentioned in the official PHP manual.
Well, probably one has to declare $argv global ony for scripts run with server. Maybe in a local environment running script in CLI $argv does not require being declared global. When I test it I post here.
But nevertherless for my case the working configuration is:
global $argv;
echo "argv0: $argv[0]\n\r"; // echoes: argv0: /server/path/to/my/script/my-script.php
echo "argv1: $argv[1]\n\r"; // echoes: argv1: test.tst
echo "argv2: $argv[2]\n\r"; // echoes: argv2: folder=0
I got the same results with $_SERVER['argv'] superglobal array.
One can make use of it like this:
$myargv = $_SERVER['argv'];
echo $myargv[1]; // echoes: test.tst
Hope that helps somebody.
I'm making a function for my users where they can upload large XML files to synchronize with my database.
When a user uploads a file to upload.php, I want to start processing the data in the background with process.php, preferably from a shell command, and redirect the user to status.php, which shows the process of the synchronization.
I need to pass some variables to the process.php script while executing it, either at least one variable with the user id and put the other variables into a text file, (Would probably prefer this so I wont have to put to much data into the exec() command.) or the user id and a bunch of $_POST variables.
One solution I had in mind is executing the PHP script like this:
exec("php -f ./process.php > /dev/null 2>/dev/null &");
This allows me to lock away process.php from http access, which is good since it's a process taking script. The only thing I need here is to pass a variable somehow, but i don't know how to do it.
So my main question is:
How do i pass a variable in the above solution?
Or do any of you have a better solution to doing this? Possibly one where i wont have to go through exec()? Keep in mind that i do not want the user to wait for the script to execute, and i need to pass at least one variable.
Update: For future reference, remember to use escapeshellarg() when passing arguments through exec() or likewise functions.
You test use it
exec("php -f ./process.php var1 var2 > /dev/null 2>/dev/null &");
And if you like get these variables values can acces with global variable $argv. If you print this var show same:
print_r($argv);
Array
(
[0] => process.php
[1] => var1
[2] => var2
)
You can pass parameters like the following.
// call process.php
exec("php -f ./process.php foo=bar bar=foo > /dev/null 2>/dev/null &");
// process.php
if ($argc > 0) {
for ($i=1;$i < $argc;$i++) {
parse_str($argv[$i],$tmp);
$_REQUEST = array_merge($_REQUEST, $tmp);
}
}
var_dump($_REQUEST);
I don't really understood your goal, but to pass an argument to an PHP-script works similar to any other shell scripts. See: http://www.php.net/manual/en/features.commandline.usage.php (Example #2)
"When a user uploads a file […], I want to start processing the data in the background" - You can't access an upload before it is finished, in PHP using CGI.
Here is my solution.
The advantage is that you can use this script for command line usage as well as for regular web usage. In case you call it from cmd the $argv variable is set, so the parse_str() part extracts the variables and puts them into the $_GET array. In case you call it from the web the $argv is not set so the values come from the url.
// executingScript.php
// You have to make percent escaping yourself
exec("php -f ./executedScript.php foo=bar%20foo bar=foo%20bar > /dev/null 2>/dev/null &");
// executedScript.php
// The if-statement avoids crashing when calling the script from the web
if (isset($argv)) {
parse_str(implode('&', array_slice($argv, 1)), $_GET);
}
This will make you able to access the variables as usual:
echo $_GET["foo"] // outputs "bar foo"
echo $_GET["bar"] // outputs "foo bar"
I have a scenario where in our php file accepts parameters from the command line.
For example we say,
php test.php 'hello'
Now the above runs on command prompt. Suppose now we want to invoke this from client end however ofcourse i do not want the System system call as that would be a bad design, i just want to directly call the function which accepts parameters from the client end and ofcourse client can be anything maybe .Net or PHP so how can I caccomplish that?
Thanks!
Put your script on a web server and accept the argument via HTTP GET or POST.
It would look something like http://hostname/test.php?argument=hello. Then, in your test.phpscript, pass the $_GET['argument'] to your function:
myfunction($_GET['argument']);
Don't forget to sanitize the input!
you may use a function that will manage command line argiments:
$param_1 = isset($argv[1]) ? $argv[1] : null;
if ($param_1 == 'function1')
function1()
elseif...
and so on.
You can make a wrapper script that puts GET parameters from your client into the command line argument array.
Let's say your client makes a request like:
hostname/testWrapper.php?params[]=hello¶ms[]=goodbye
Your wrapper script testWrapper.php could then look like
<?php
$params = $_GET['params'];
foreach ($params as $i => $param)
$_SERVER['argv'][$i + 1] = $param;
$_SERVER['argc'] = count($_GET['params'] + 1);
include ('test.php');
?>
This assumes that your test.php uses $_SERVER['argv/argc']to read command line arguments. It may use $argv and $argc instead (if 'register_argc_argv' is enabled in your php.ini), in which case you just use those in your wrapper script instead of $_SERVER[...].
Notice that we have to insert the parameters with an offset of 1 (i.e. $params[0] becomes $_SERVER['argv'][1]. This is because when the script is called from the command line, the first parameter $_SERVER['argv'][0] is the script name.
Lastly, unless you are absolutely sure that your test.php sanitizes the parameters, you have to do it in the wrapper script.