You probably need to chdir to the correct directory before calling the script. This way you can ensure what directory your script is "in" before calling the shell command.
$old_path = getcwd();
chdir('/my/path/');
$output = shell_exec('./script.sh var1 var2');
chdir($old_path);
Answer from Robert K on Stack OverflowYou probably need to chdir to the correct directory before calling the script. This way you can ensure what directory your script is "in" before calling the shell command.
$old_path = getcwd();
chdir('/my/path/');
$output = shell_exec('./script.sh var1 var2');
chdir($old_path);
Your shell_exec is executed by www-data user, from its directory. You can try
putenv("PATH=/home/user/bin/:" .$_ENV["PATH"]."");
Where your script is located in /home/user/bin Later on you can
$output = "<pre>".shell_exec("scriptname v1 v2")."</pre>";
echo $output;
To display the output of command. (Alternatively, without exporting path, try giving entire path of your script instead of just ./script.sh
Bash script to run php script - Stack Overflow
How to run a bash script from PHP - Unix & Linux Stack Exchange
Any way to SAFELY execute shell scripts from PHP?
apache - Executing a shell script from a PHP script - Stack Overflow
Videos
If you have PHP installed as a command line tool (try issuing php to the terminal and see if it works), your shebang (#!) line needs to look like this:
#!/usr/bin/php
Put that at the top of your script, make it executable (chmod +x myscript.php), and make a Cron job to execute that script (same way you'd execute a bash script).
You can also use php myscript.php.
Sometimes PHP is placed in non standard location so it's probably better first locate it and then try to execute.
#!/usr/bin/env bash
PHP=`which php`
$PHP /path/to/php/file.php
The problem here is that you are quoting the entiore command you are trying to run as a single variable. As a result, you're not running php with foo.php as an argument but instead are attempting to execute a file called php foo.php. Here's a simpler example to show you what I mean:
$ var1="echo "
$ var2="foo"
$ set -x ## debugging info
var1$var2"
+ 'echo foo' ### The shell tries to execute both vars as a single command
bash: echo foo: command not found
var1" "$var2"
+ 'echo ' foo ### The shell tries to execute 'echo ' (echo with a space)
bash: echo foo: command not found
So, the right way is to remove the space and quote each variable separately:
$ var1="echo"
$ var2="foo"
var1" "$var2"
If you do that though, you'll hit the next error. The . is the source command. That tries to read a shell script and execute it in the current session. You are giving it a php script instead. That won't work, you need to execute it, not source it.
Finally, always avoid using CAPITAL variable names. The shell's reserved variables are capitalized so it's a good idea to always use lower case variable names for your scripts.
Putting all this together (with a few other minor improvements), what you want is something like:
#!/bin/sh
list="/path/to/my/site/dir"
config="/usr/bin/php"
for i in "$list"
do
"$config" "$i"/test.php
done
The problem in your code is the line:
. "${CONFIG}${i}/test.php"
Remove the .
Here is another example:
$ ls -l
-rwxrwxr-x 1 bg bg 67 Oct 20 09:42 index.php
-rwxrwxr-x 1 bg bg 68 Oct 20 09:43 test.sh
index.php
<?php
shell_exec('echo Hello > /tmp/hello.txt');
?>
test.sh
#!/bin/bash
/usr/bin/php index.php
I have a website accessible from https://exampleurl.com:1234 (i.e. nonstandard port).
After logging in, this website gives my users a GUI and a few buttons. The buttons interact with PHP scripts on an Unraid VM, which then launch shell scripts. The shell scripts are used for controlling streams via streaming software called "OBS-Studio".
Here's an example:
my.php
<?php
$output = shell_exec("/bin/bash /var/www/html/streamstart.sh");
echo $output;
?>
streamstart.sh
#!/bin/bash
obs-cmd streaming startI'm relatively new to PHP, and I'm not sure how this could be exploited. Is there a way to make this more secure?
I have set the password for my users to be extremely secure, but that feels like the only line of defense right now.
I may be wrong, but I believe that sudoers also restricts parameters that can be passed to a command/script, not just the command itself.
If you try to run your .sh without the parameter it will likely work e.g.
sudo /bin/bash /var/www/my_bash_script.sh
So, to tell sudoers to allow that script to be run with any parameters (by apache), you would need to adjust the line like so:
apache ALL=(ALL) NOPASSWD:/var/www/my_bash_script.sh *
The wildcard would allow apache to run that script with any parameters.
You may also need /bin/bash in that line but I'm not certain
apache ALL=(ALL) NOPASSWD: /bin/bash /var/www/my_bash_script.sh *
If anyone can confirm or refute my understanding of this it would be much appreciated
You can use the following settings
Cmnd_Alias SVNUP = /root/webhooks/svn_update.sh
apache ALL=(ALL) NOPASSWD: SVNUP
Create simple test script
# cat test.sh
#!/bin/bash
set -u
echo "Param1: $1"
Make simple tests
$ id alex
uid=506(alex) gid=506(alex) groups=506(alex)
$ cat /root/webhooks/test.sh
cat: /root/webhooks/test.sh: Permission denied
$ sudo /root/webhooks/test.sh val1
Param1: val1
$ sudo /root/webhooks/test.sh
/root/webhooks/test.sh: line 5: $1: unbound variable
But you must be a really careful due to variable expansions, for e.g.
$ sudo /root/webhooks/test.sh "$(rm -fr ~/*)"
P.S. As alternative you can use mpm-itk with apache and run this particular vhosts with specific user.
I would have a directory somewhere called scripts under the WWW folder so that it's not reachable from the web but is reachable by PHP.
e.g. /var/www/scripts/testscript
Make sure the user/group for your testscript is the same as your webfiles. For instance if your client.php is owned by apache:apache, change the bash script to the same user/group using chown. You can find out what your client.php and web files are owned by doing ls -al.
Then run
<?php
$message=shell_exec("/var/www/scripts/testscript 2>&1");
print_r($message);
?>
EDIT:
If you really want to run a file as root from a webserver you can try this binary wrapper below. Check out this solution for the same thing you want to do.
Execute root commands via PHP
Without really knowing the complexity of the setup, I like the sudo route. First, you must configure sudo to permit your webserver to sudo run the given command as root. Then, you need to have the script that the webserver shell_exec's(testscript) run the command with sudo.
For A Debian box with Apache and sudo:
Configure sudo:
As root, run the following to edit a new/dedicated configuration file for sudo:
visudo -f /etc/sudoers.d/Webserver(or whatever you want to call your file in
/etc/sudoers.d/)Add the following to the file:
www-data ALL = (root) NOPASSWD: <executable_file_path>where
<executable_file_path>is the command that you need to be able to run as root with the full path in its name(say/bin/chownfor the chown executable). If the executable will be run with the same arguments every time, you can add its arguments right after the executable file's name to further restrict its use.For example, say we always want to copy the same file in the /root/ directory, we would write the following:
www-data ALL = (root) NOPASSWD: /bin/cp /root/test1 /root/test2
Modify the script(testscript):
Edit your script such that
sudoappears before the command that requires root privileges(saysudo /bin/chown ...orsudo /bin/cp /root/test1 /root/test2). Make sure that the arguments specified in the sudo configuration file exactly match the arguments used with the executable in this file. So, for our example above, we would have the following in the script:sudo /bin/cp /root/test1 /root/test2
If you are still getting permission denied, the script file and it's parent directories' permissions may not allow the webserver to execute the script itself. Thus, you need to move the script to a more appropriate directory and/or change the script and parent directory's permissions to allow execution by www-data(user or group), which is beyond the scope of this tutorial.
Keep in mind:
When configuring sudo, the objective is to permit the command in it's most restricted form. For example, instead of permitting the general use of the cp command, you only allow the cp command if the arguments are, say, /root/test1 /root/test2. This means that cp's arguments(and cp's functionality cannot be altered).
Passing parameters to a shell script from PHP.
Its all about the "strings", and when to "double quote" for expansion.
<?php
/* exec("/csvexport.sh $table"); */
/* double quote here because you want PHP to expand $table */
/* Escape double quotes so they are passed to the shell because you do not wnat the shell to choke on spaces */
$command_with_parameters = "/path/csvexport.sh \"${table}\"";
$output_from_command = "";
$command_success = "";
/* double quote here because you want PHP to expand $command_with_parameters, a string */
exec("${command_with_parameters}", $output_from_command, $command_success);
/* or to keep it simple */
exec("/path/csvexport.sh \"${table}\"");
/* show me what you got */
echo"${command_success}\n${output_from_command}\n";
?>
BTW: I did not test this snippet.
I'm not a PHP guy, but it seems you'll need to do something like
exec(escapeshellcmd("/csvexport.sh \"$query\" $table"));
Does PHP have a function where you can call the command and pass the arguments separately?
some_exec_function("/csvexport.sh", $query, $table); # ???