I've seen a few of these exec/shell_exec questions but I can't tell what I'm doing incorrectly.
I'm making an embedded web application that will allow a user to change the ip address of the device they are connected to. I have a bash script that works from an SSH terminal, but not from exec() or shell_exec() in PHP. This is all running on a Raspberrypi, Nginx, and PHP 7.3.
Here is the bash script:
#! /bin/bash
# GLOBAL
regex_selector=".*"
file_name="/etc/dhcpcd.conf"
# IP
ip=$1
ip_flag="static ip_address="
new_ip="$ip_flag$ip"
command="s!$ip_flag$regex_selector!$new_ip!g"
echo "$command"
sudo sed -i "${command}" "$file_name"
# ROUTER
# router=$2
# router_flag="static routers="
# new_router="$router_flag$router"
# command="s!$router_flag$regex_selector!$new_router!g"
# echo "$command"
# sudo sed -i "$command" "$file_name"
# DONE
echo "settings updated"
sudo reboot
Here is the PHP:
...
$ip = $input_[1];
$command = "bash change_ip_settings.sh ".$ip;
$output = [];
exec($command, $output);
foreach($output as $key => $value) {
echo("$key: $value<br>");
}
echo("<br>");
var_dump($output);
...
Here is the output on the page:
0: s!static ip_address=.*!static ip_address=192.168.200.2!g
1: settings updated
array(2) { [0]=> string(56) "s!static ip_address=.*!static ip_address=192.168.200.2!g" [1]=> string(16) "settings updated" }
As you can see, the various echo commands before and after the sed are executing. Also, there is no error message returned from exec(). Finally, this same script does run when called from an ssh terminal.
I know this is some permission issue but I'm not sure what to do. The bash file, php file, and target file all have 777 permissions (given by chmod).
Thanks for any help.
UPDATE:
I've followed the advice given in this post but sed still does not work when used in a bash script being called by php via exec(). I have added www-data to my sudoers file using visudo. I know the user is www-data because I ran a whoami in my bash script file and echoed the results. I have tried to remove sudo from the bash scrip line with sed but that has had no effect. All indications are that the script executes, there are no errors in the output of exec(), but when I check the file, the target line has not changed. Again, the script does work when run from both an ssh and local terminal so I know this must be some sort of permissions issue. I'm thinking I may also need to add the path to sed in sudoers which is what I will try next.
Sudoers:
www-data ALL=NOPASSWD: /path/to/my/script
Thanks again for any help.
SOLUTION:
I resolved this issue by not using a bash script for the sed operation. Initially, I wanted to separate the system file functions from PHP and use bash. However, I could not get PHP to use sed inside a bash script. So, I just called sed directly in exec() and it works fine. This is not ideal as far as I'm concerned because I don't want my page script to parse my system files but I'll have to look into granting www-data the correct permissions to use sed in a bash file.
Here is what I had:
...
$ip = $input_[1];
$command = "bash change_ip_settings.sh ".$ip;
$output = [];
exec($command, $output);
...
Here is what works:
...
$file_name = "/etc/dhcpcd.conf";
$parser = new DHCPCDParser($file_name);
$line_number = $parser->get_line_number($interface, "static ip_address");
$command = $line_number."s!.*!static ip_address=$input_[1]!";
$command = "sudo sed -i '$command' $file_name";
exec($command, $output, $result);
exec("sudo reboot");
...
And the changes I had to make to /etc/sudoers:
...
www-data ALL=(ALL) NOPASSWD: /usr/bin/ # needed for sed
www-data ALL=(ALL) NOPASSWD: /usr/sbin/ # needed for reboot
...