pass crontab a variable and read it from PHP? - php

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.

Related

How to pass and read parameters while php.exe compile process on Windows (cmd)

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

how can access argv and options together in php through command line arguments

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.

calling exec on a php file and passing parameters?

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.

PHP passing $_GET in the Linux command prompt

Say we usually it access via
http://localhost/index.php?a=1&b=2&c=3
How do we execute the same on a Linux command prompt?
php -e index.php
But what about passing the $_GET variables? Maybe something like php -e index.php --a 1 --b 2 --c 3? I doubt that'll work.
From this answer on Server Fault:
Use the php-cgi binary instead of just php, and pass the arguments on the command line, like this:
php-cgi -f index.php left=1058 right=1067 class=A language=English
Which puts this in $_GET:
Array
(
[left] => 1058
[right] => 1067
[class] => A
[language] => English
)
You can also set environment variables that would be set by the web server, like this:
REQUEST_URI='/index.php' SCRIPT_NAME='/index.php' php-cgi -f index.php left=1058 right=1067 class=A language=English
Typically, for passing arguments to a command line script, you will use either the argv global variable or getopt:
// Bash command:
// php -e myscript.php hello
echo $argv[1]; // Prints "hello"
// Bash command:
// php -e myscript.php -f=world
$opts = getopt('f:');
echo $opts['f']; // Prints "world"
$_GET refers to the HTTP GET method parameters, which are unavailable on the command line, since they require a web server to populate.
If you really want to populate $_GET anyway, you can do this:
// Bash command:
// export QUERY_STRING="var=value&arg=value" ; php -e myscript.php
parse_str($_SERVER['QUERY_STRING'], $_GET);
print_r($_GET);
/* Outputs:
Array(
[var] => value
[arg] => value
)
*/
You can also execute a given script, populate $_GET from the command line, without having to modify said script:
export QUERY_STRING="var=value&arg=value" ; \
php -e -r 'parse_str($_SERVER["QUERY_STRING"], $_GET); include "index.php";'
Note that you can do the same with $_POST and $_COOKIE as well.
Sometimes you don't have the option of editing the PHP file to set $_GET to the parameters passed in, and sometimes you can't or don't want to install php-cgi.
I found this to be the best solution for that case:
php -r '$_GET["key"]="value"; require_once("script.php");'
This avoids altering your PHP file and lets you use the plain php command. If you have php-cgi installed, by all means use that, but this is the next best thing. I thought this options was worthy of mention.
The -r means run the PHP code in the string following. You set the $_GET value manually there, and then reference the file you want to run.
It's worth noting you should run this in the right folder, often, but not always, the folder the PHP file is in. 'Requires' statements will use the location of your command to resolve relative URLs, not the location of the file.
I don't have a php-cgi binary on Ubuntu, so I did this:
% alias php-cgi="php -r '"'parse_str(implode("&", array_slice($argv, 2)), $_GET); include($argv[1]);'"' --"
% php-cgi test1.php foo=123
<html>
You set foo to 123.
</html>
%cat test1.php
<html>You set foo to <?php print $_GET['foo']?>.</html>
Use:
php file_name.php var1 var2 varN
Then set your $_GET variables on your first line in PHP, although this is not the desired way of setting a $_GET variable and you may experience problems depending on what you do later with that variable.
if (isset($argv[1])) {
$_GET['variable_name'] = $argv[1];
}
The variables you launch the script with will be accessible from the $argv array in your PHP application. The first entry will the name of the script they came from, so you may want to do an array_shift($argv) to drop that first entry if you want to process a bunch of variables. Or just load into a local variable.
Try using WGET:
WGET 'http://localhost/index.php?a=1&b=2&c=3'
Option 1: php-cgi
Use 'php-cgi' in place of 'php' to run your script. This is the simplest way as you won't need to specially modify your PHP code to work with it:
php-cgi -f /my/script/file.php a=1 b=2 c=3
Option 2: If you have a web server
If the PHP file is on a web server you can use 'wget' on the command line:
wget 'http://localhost/my/script/file.php?a=1&b=2&c=3'
Or:
wget -q -O - "http://localhost/my/script/file.php?a=1&b=2&c=3"
Accessing the variables in PHP
In both option 1 & 2, you access these parameters like this:
$a = $_GET["a"];
$b = $_GET["b"];
$c = $_GET["c"];
If you have the possibility to edit the PHP script, you can artificially populate the $_GET array using the following code at the beginning of the script and then call the script with the syntax: php -f script.php name1=value1 name2=value2
// When invoking the script via CLI like
// "php -f script.php name1=value1 name2=value2",
// this code will populate $_GET variables called
// "name1" and "name2", so a script designed to
// be called by a web server will work even
// when called by CLI
if (php_sapi_name() == "cli") {
for ($c = 1; $c < $argc; $c++) {
$param = explode("=", $argv[$c], 2);
$_GET[$param[0]] = $param[1]; // $_GET['name1'] = 'value1'
}
}
If you need to pass $_GET, $_REQUEST, $_POST, or anything else you can also use PHP interactive mode:
php -a
Then type:
<?php
$_GET['a'] = 1;
$_POST['b'] = 2;
include("/somefolder/some_file_path.php");
This will manually set any variables you want and then run your PHP file with those variables set.
At the command line, paste the following:
export QUERY_STRING="param1=abc&param2=xyz" ;
POST_STRING="name=John&lastname=Doe" ; php -e -r
'parse_str($_SERVER["QUERY_STRING"], $_GET); parse_str($_SERVER["POST_STRING"],
$_POST); include "index.php";'
I just pass them like this:
php5 script.php param1=blabla param2=yadayada
It works just fine. The $_GET array is:
array(3) {
["script_php"]=>
string(0) ""
["param1"]=>
string(6) "blabla"
["param2"]=>
string(8) "yadayada"
}
Use:
php -r 'parse_str($argv[2],$_GET);include $argv[1];' index.php 'a=1&b=2'
You could make the first part as an alias:
alias php-get='php -r '\''parse_str($argv[2],$_GET);include $argv[1];'\'
Then simply use:
php-get some_script.php 'a=1&b=2&c=3'
Or just (if you have Lynx):
lynx 'http://localhost/index.php?a=1&b=2&c=3'

How to do command line from PHP script

I need to write a script that will give users info on a given Unix account (the same Unix server that the script lives on). Mostly thing kinds of things that are in the passwd file or available via finger.
PHP is in safe-mode, so I can't access the passwd file via something built into php like file_get_contents(). Also, because it's in safe mode, various other command-line functions are disabled.
I thought I could get the info via a socket (no clue yet what that means, but I thought I'd try) but I get a fatal error that socket_create() is an unknown function. I pulled up the php-config file (which I can't change, FYI), and sure enough, sockets are not enabled.
However, while I was in there, I saw the line '--with-exec-dir=' with no actual directory set.
So then I remembered that when I was trying EVERY command line function, that some threw "not allowed in safe-mode" type errors, while others did nothing at all. If I put something like:
echo "[[";
exec("finger user");
echo "]]";
I'd end up with [[]]. So no errors, just no results either.
Bottom line:
Is there something I haven't tried? (in general)
Is there a runtime config option I can set to make exec() work?
quick note: I tried passthru() as well, specifically passthru("pwd") with still no output.
update
based on feedback, I tried both of the following:
$stuff = exec("pwd", $return);
echo "stuff=".$stuff."\n";
echo "return=";
print_r($return);
which results in:
stuff=
return=Array
(
)
and
$stuff = passthru("pwd", $return);
echo "stuff=".$stuff."\n";
echo "return=";
print_r($return);
which results in:
stuff=
return=1
The 1 sounds hopeful, but not what I want yet.
Idea
So this is actually an update of an already existing script that (please don't ask) I don't have access to. It's a perl script that's called via cgi. Is there a way to do php via cgi (so I don't have to deal with perl or rely on the older code)?
I'm afraid you can't do that in safe-mode. You have to remove the safe-mode if you have control of the server configuration.
I think you can't rely on sockets to read local files, sockets are used for network related things.
exec doesn't inherently return any data.
Try something like,
exec("finger user",$output);
echo "[[";
foreach($output as $key => $value){
echo $value;
}
echo "]]";
Exec returns a value, so do:
$var = exec("finger user");
and then parse the output to get what you want. You can get return status by adding in an optional variable thus:
exec("finger user", $var, $return_status);
or just:
echo exec("finger user");
if all you want is to see the output.
Thanks to all that responded, the following is what finally worked:
Create a cgi-bin folder
Add the following to the top of the php script:
#!/usr/local/bin/php-cgi
I don't know if this is something special on my server configuration, but I can run exec() and get what I'm after.

Categories