Is it possible to pass BASH associative arrays as argv to PHP scripts?
I have a bash script, that collects some variables to a bash associative array like this. After that, I need to send it to PHP script:
typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)
php script.php --data ${DATA[#]}
From PHP script, i need to access the array in following manner:
<?php
$vars = getopt("",array(
"data:"
));
$data = $vars['data'];
foreach ($data as $k=>$v) {
echo "$k is $v";
}
?>
What I've tried
Weird syntax around the --data parameter follows advice from a great post about bash arrays from Norbert Kéri how to force passed parameter as an array:
You have no way of signaling to the function that you are passing an array. You get N positional parameters, with no information about the datatypes of each.
However this sollution still does not work for associative arrays - only values are passed to the function. Norbert Kéri made a follow up article about that, however its eval based solution does not work for me, as I need to pass the actual array as a parameter.
Is the thing I'm trying to achieve impossible or is there some way? Thank you!
Update: What I am trying to accomplish
I have a few PHP configuration files of following structure:
<?php
return array(
'option1' => 'foo',
'option2' => 'bar'
)
My bash script collects data from user input (through bash read function) and stores them into bash associative array. This array should be later passed as an argument to PHP script.
php script.php --file "config/config.php" --data $BASH_ASSOC_ARRAY
So instead of complicated seds functions etc. I can do simple:
<?php
$bash_input = getopt('',array('file:,data:'));
$data = $bash_input['data'];
$config = require($config_file);
$config['option1'] = $data['option1'];
$config['option2'] = $data['option2'];
// or
foreach ($data as $k=>$v) {
$config[$k] = $v;
}
// print to config file
file_put_contents($file, "<?php \n \n return ".var_export($config,true).";");
?>
This is used for configuring Laravel config files
Different Approach to #will's
Your bash script:
typeset -A DATA
foo=$(some_bash_function "param1" "param2")
bar=$(some_other_bash_function)
php script.php "{'data': '$foo', 'data2': '$bar'}"
PHP Script
<?php
$vars = json_decode($argv[1]);
$data = $vars['data'];
foreach ($data as $k=>$v) {
echo "$k is $v";
}
?>
EDIT (better approach) Credit to #will
typeset -A DATA
DATA[foo]=$(some_bash_function "param1" "param2")
DATA[bar]=$(some_other_bash_function)
php script.php echo -n "{"; for key in ${!DATA[#]}; do echo - "'$key'":"'${DATA[$key]}'", | sed 's/ /,/g' ; done; echo -n "}"
this does what you want (i think) all in one bash script. You can obviously move the php file out though.
declare -A assoc_array=([key1]=value1 [key2]=value2 [key3]=value3 [key4]=value4)
#These don't come out necesarily ordered
echo ${assoc_array[#]} #echos values
echo ${!assoc_array[#]} #echos keys
echo "" > tmp
for key in ${!assoc_array[#]}
do
echo $key:${assoc_array[$key]} >> tmp # Use some delimeter here to split the keys from the values
done
cat > file.php << EOF
<?php
\$fileArray = explode("\n", file_get_contents("tmp"));
\$data = array();
foreach(\$fileArray as \$line){
\$entry = explode(":", \$line);
\$data[\$entry[0]] = \$entry[1];
}
var_dump(\$data);
?>
EOF
php file.php
the escaping is necessary in the cat block annoyingly.
Related
If I execute an R program through macOS Terminal it works fine, but if I execute that program through PHP exec() I get an error which says "Rscript not found".
submit.php:
<?php
// print "hello";
$a = $_POST['a'];
$b = $_POST['b'];
// echo shell_exec("calc");
$output = exec("Rscript /xampp/htdocs/demo/1.R ".$a." ".$b);
print $output
?>
1.R:
setwd("C:/xampp/htdocs/demo")
print("hello")
args=commandArgs(trailingOnly = TRUE)
a = args[1]
b = args[2]
c = as.numeric(a)+as.numeric(b)
cat(c)
You need to tell the command interpreter where Rscript is located. In a normal login, you'd have a long PATH variable to search through, but when running from PHP you have a much more limited path. To figure out where the executable is located, type which Rscript from Terminal. Use the resulting path in your PHP script.
Also note that dumping raw user input into shell commands is a very bad idea. You should always use escapeshellarg() to make sure the input is sanitized. I would also suggest capturing the full output in the event that R outputs more than one line.
<?php
$a = escapeshellarg($_POST["a"]);
$b = escapeshellarg($_POST["b"]);
$r = "/xampp/htdocs/demo/1.R";
$lastline = exec("/usr/local/bin/Rscript $r $a $b", $output, $return);
// you could check the value of $return for non-zero values as well
// full output is returned as an array
echo implode("\n", $output);
Finally, you'll want to check your setwd() command in the R script. Might have some trouble with C: on a Mac! ;)
I am trying to execute a C program using the shell_exec command, which needs arguments to be passed. It is working for one input, but not working for others. I tried to run the C program through terminal, it is working for all the inputs.
This is my execprog.php file. I have to give 2 inputs as command line arguments to file. /var/www/project is the path.
$query = "/var/www/project/./a.out /var/www/project/constraints.txt /var/www/project/constraints_keyword.txt /var/www/project/FIB.txt /var/www/project/ANS.txt";
echo $query;
$var = shell_exec($query);
echo $var;
<?php
$query = "/var/www/project/./a.out";
$arguments = array
(
'/var/www/project/constraints.txt',
'/var/www/project/constraints_keyword.txt',
'/var/www/project/FIB.txt',
'/var/www/project/ANS.txt'
);
$string = '';
for($i=0;$i<count($arguments);$i++)
$string.= ' %s';
$command = vsprintf("{$query}{$string}", $arguments);
$var = shell_exec($command);
echo $var;
As you it works on the terminal and not on apache then apache's php.ini file may be disabling the use of shell_exec().
See http://www.php.net/manual/en/ini.core.php#ini.disable-functions
Your apache's php.ini file may look something like
disable_functions=exec,passthru,shell_exec,system,proc_open,popen
Remove shell_exec from this list and restart the web server, although this is a security risk and I don't recommend it.
In general functions such as exec,shell_exec and system are always used to execute the external programs. Even a shell command can also be executed. If these two functions are enabled then a user can enter any command as input and execute into your server. So usually people disable in apache config as disable_functions to secure their site.
It works for me - Here is test run
Sample test c code
[akshay#gold tmp]$ cat test.c
#include<stdio.h>
int main(int args, char *argv[]) {
int i = 0;
for (i = 0; i < args; i++)
printf("Arg[%d] = %s\n",i, argv[i]);
return 0;
}
Compile
[akshay#gold tmp]$ gcc test.c
Sample php script
[akshay#gold tmp]$ cat test.php
<?php
$query = "/tmp/./a.out /var/www/project/constraints.txt /var/www/project/constraints_keyword.txt /var/www/project/FIB.txt /var/www/project/ANS.txt";
$var = shell_exec($query);
echo $var;
?>
Execution and output
[akshay#gold tmp]$ php test.php
Arg[0] = /tmp/./a.out
Arg[1] = /var/www/project/constraints.txt
Arg[2] = /var/www/project/constraints_keyword.txt
Arg[3] = /var/www/project/FIB.txt
Arg[4] = /var/www/project/ANS.txt
I am trying to pass array from shell_exec and want to access the array in bash file. I tried to research from many websites but did not find the proper solution for it. Please help me out to resolve this issue. Thanks in advance
Php Code
$array= $countries_array; // Countries array from database
shell_exec('sh get_countries.sh '.$array);
Bash File countries.sh
echo $1;
I have understanding of array in bash file:
#!/bin/bash
declare -a myArray
myArray=("$#")
for arg in "${myArray[#]}"; do
echo "$arg"
done
But I am confused, how to fetch $array in bash file?
Also for passing variable, use the following code:
$var=shell_exec('sh get_countries.sh hello');
echo $var;
Bash File==>
echo $1
Output will be hello
echo 'sh countries.sh '.join(' ',$data);
output==>
sh countries.sh a940cfb9-2abe-5835-9d69-41c0d992c38d 768bd771-359f-5da0-9f66-ccae4460f98d 778f384c-8496-56f1-96e6-4a03b2c22ff5 45ba4726-bba8-5e7b-ab62-c0e30df2e81b c8eb2a47-dc44-5439-80db-b6c7b7c1d30c c875edce-2177-55c9-bfa0-c4af3b9ac281 21c6ea3f-b6f3-5fa6-b693-863dddbe22d3 944d2f91-e4a3-53e3-9379-0a4cb6819dd5 a3db4ca5-7442-529d-bbf2-aa0dc74dd3e3 c0698faa-8a83-5aea-8f41-e8d993ff7fb4 4d0ab432-6e40-5e5d-8304-9b2108cf6a0f 54522d73-15bd-5061-aaf3-beb7cc6a0ed2 4d4a7d51-7af4-538d-a09e-92335eecb7b4 be9406d5-26af-52d7-a141-1f8d299beb9b 89bb6275-5047-5f0f-a369-8e0c9028654c 24151e55-c1ba-5ca3-8728-2558faf308ea 13895b30-322f-5886-8eba-7272fb4f990f a31d7cc7-49ea-5746-be3e-b15fe3894d43 e5505a29-37c5-582a-872a-6a65d74c8ded 92c4a93d-c91c-55eb-8f9f-fcb675d27cee 20c7086e-1599-52e6-8d8e-287b9e0cb58b 48a2bc90-14e0-575d-a0de-31140eb885ac 2d3772ca-9a65-5707-ad22-f53076acc3c3 731863e8-6889-5691-ad6e-4fd34c747889 762244b1-f952-5a34-8f71-eb2d856be293 ddb0eb7e-4ee5-56b7-a65a-d8dcf8238618 ff861dba-13f3-5282-afc2-9b9d7de3c18a eeb07bf4-a752-5289-ae47-3d549c54a552 c40bb588-4db7-5602-a12c-2697a9bf671a b89c6a26-87e0-5deb-ba28-f9cc39d7aeeb 11989abf-c6c0-5593-8451-e199e1a54c16 c9b19a1f-005c-5d0e-b7e1-5f52697cf4cf cfa46bd6-ac53-5d61-be9d-ec0d949138dc fe584292-01ab-5041-8c34-c824b8e4c5a7 2230ef16-921c-5fe1-ba69-79cf7c5ecff3 a1834c7f-bb69-59a4-b596-633590314bf6 7a41586b-927a-5100-9b9e-bff61e47440e e9a04859-a739-5b19-beda-b1d715f0b5da 2ba8a83a-92d0-5e18-81fa-1c09bcb4f1e2 4530e663-b036-5f33-8ad5-78dbf672f1cc 67ce40ed-f6c5-52a0-8eed-0b1c351765cb e6081884-fc3e-5cd5-8fdf-b4256aef251c 21668da0-a24e-5f74-ae14-32111c3ee78b 1a7f1847-87ad-5255-8011-177535b5979d e8d56819-7de5-567c-8672-55ea33c90676 cdc1c35a-2455-57e4-a8e5-4e01fd4f2d07 3f137a13-7011-5306-95e0-d713df89f9e6 e2153d20-e940-5c15-892c-a26e41afb9ca eb0e5967-3e1d-5eef-a453-0c74eb9af66a 0de046fc-40a6-599a-884f-18efb8281dc8 769bba0e-4b25-55e9-95c2-7e32096a05e7 e3cc0250-61bb-55c5-b3d4-90f3fb8a3290 8a9beccd-86d9-5150-b4ab-624e007c3594 91c72559-f535-5067-9989-9e0095f97ce3 41147580-3444-5ace-9e67-1f0f060474fd b1cda433-3059-5240-b59b-91694336fc35 7d042de8-ed7a-5faf-9a16-2ae409e5a2f8 f116b2b7-490d-5451-abc3-1141868da92e 1f19bb92-23fc-5f2e-ac5e-bbc3f9965aeb
If your php variable $array is a php Array, you need to convert it to a string to do the call, eg:
shell_exec('sh get_countries.sh '.join(' ',$array));
Then your countries.sh should be exactly what you gave as an example:
#!/bin/bash
declare -a myArray
myArray=("$#")
for arg in "${myArray[#]}"; do
echo "$arg"
done
Make sure you permit the file for execution with chmod a+rx countries.sh.
I am writing my first BASH script to automate configuration of my (Laravel) web projects.
I have some config files (app/config/local/database.php,app/config/app.php) with PHP arrays that I need to access and modify. For example ...
'providers' => array(
/** Append new service provider value, if it does not exist already */
'Illuminate\Foundation\Providers\ArtisanServiceProvider',
'Illuminate\Auth\AuthServiceProvider',
// ...
)
... or ...
'mysql' => array(
/** Replace value under key "database" to "test_db" */
'database' => 'homestead',
'username' => 'homestead',
)
So far I was using sed expressions like this:
$LV_DB_NAME="test_db"
$LV_DB_FILE="app/config/local/database.php"
gsed -i "s/'database' .*/'database' => '$LV_DB_NAME',/g" $LV_FILE_DB_CONFIG
This feels a little messy to me, especially in the case of example 1.
What would be awesome
Is there any way to get PHP arrays to BASH arrays and work with like you would in PHP?
Example 1
if (!in_array($new_provider, $providers)) {
$providers[] = $new_provider;
}
Example 2
$config['mysql']['database'] = $database_name
Update: What would also be awesome
If there is any other common way how to modify PHP arrays using terminal, I would be glad if you point me to it! I'm sure I'm not the only one who needs to modify PHP configuration arrays using terminal.
mTorres was actually right. If your machine has php cli installed (which is probable), You can easily jump into PHP from your bash scripts. There are multiple ways to do so, I finally settled with this:
print_s "Putting data to file \"$PATH\" ... "
export PATH=$PATH
export DATA_JSON=$DATA_JSON
/usr/bin/php << 'EOF'
<?php
$path = getenv("PATH");
$data = getenv("DATA_JSON");
$data = json_decode($data);
$config = (file_exists($path) && is_array($config_data = require($path))) ? $config_data : array();
foreach ($data as $k => $v) {
$config[$k] = $v;
}
file_put_contents($path, "<?php \n \n return ".var_export($config,true).";");
?>
EOF
}
There are some gotchas with passing associative arrays in BASH, check my other question: Pass BASH associative arrays to PHP script
I'm trying to run a C program of adding two numbers with PHP in a web browser. But when I run the command
exec"gcc name.c -o a & a" it
returns some garbage result like sum is : 8000542.00. It doesn't ask for any input.
I want to give inputs to scanf from the browser. Please suggest to me how can I resolve my problem.
I have tried this but couldn't handle it successfully.
$desc = array(0=> array ('pipe','w'), 1=> array ('pipe','r'));
$cmd = "C:\xampp\htdocs\add.exe";
$pipes=array();
$p = proc_open($cmd,$desc,$pipes);
if(is_resource($p))
{
echo stream_get_contents($pipes[0]);
fclose($pipes[0]);
$return_value=proc_close($p);
echo $return_value;