File System Permissions
It is likely that in your case the script is not executed due to insufficient file system permissions. In Linux, you are allowed to execute a file by just writing a path to the file, if the file has executable bit set for the current user, or the user's group, e.g.:
~/scripts/abc.php
./script.sh
Otherwise, you should pass the file as an argument for appropriate program, e.g.:
php ~/scripts/abc.php
/usr/bin/php ./script.php
bash ./script.sh
You can check the file system permissions with ls
, or stat
commands, for instance:
$ stat --format='perm: %A | user: %U | group: %G' 1.sh
perm: -rwxr-xr-x | user: ruslan | group: users
$ ls -l 1.sh
-rwxr-xr-- 1 ruslan users 1261 Nov 26 11:47 1.sh
In the example above, executable bits are set for user ruslan
and for group users
, but not set for others (r--
). The others are allowed only to read (r
) the file, but not to execute, or write to the file.
To set the executable bits use chmod
command, e.g.:
# For the user
chmod u+x file.sh
# For the group
chmod g+x file.sh
A better control over the command execution
The shell_exec
function returns the contents written to the standard output descriptor. It returns NULL
, if the command prints nothing, or fails. For example:
$out = shell_exec("ls -l inexistent-file");
var_dump($out); // NULL
So you have no good control over the error conditions with shell_exec
. I recommend using prop_open
instead:
$cmd = 'ls -l 1.sh inexistent-file';
// Descriptors specification
$descriptors = [
1 => ['pipe', 'w'], // standard output
2 => ['pipe', 'w'], // standard error
];
// Open process for the command
$proc = proc_open($cmd, $descriptors, $pipes);
if (!is_resource($proc))
die("failed to open process for $cmd");
if ($output = stream_get_contents($pipes[1])) {
echo "output: $output\n";
}
fclose($pipes[1]);
if ($errors = stream_get_contents($pipes[2])) {
fprintf(STDERR, "Errors: %s\n", $errors);
}
fclose($pipes[2]);
// Close the process
if (($status = proc_close($proc)) != 0)
fprintf(STDERR, "The command failed with status %d\n", $status);
Shebang
Consider using shebang for the executable scripts. Examples:
#!/bin/bash -
#!/usr/bin/php