1

Okay, happy to accept down votes to get to the bottom of my problem. I am brand new to Linux but have hosted my PHP based site on a Linux cloud server and need to run a FFMPEG script to convert a video. Under windows I have the full application working but under Linux I can't seem to get a basic script working and was wondering if someone can point me in the right direction. I have read the myriad posts on this, for example, Run bash Command from PHP but it does not help me get to the bottom of it.

Here is what I have so far.

$old_path = getcwd();
chdir('videos/');
$new_path = getcwd();
echo('newpath '.$new_path); <-- this outputs 'old_path/videos'
$temp=  shell_exec('./testScript.sh');
echo ($temp) <-- produces nothing

Test script testScript.sh is in the video directory and is simply

echo "hello world"

Thanks...

Community
  • 1
  • 1

3 Answers3

2

First thing to do is check that PHP will actually allow to run an a shell script.

Run the following at the command prompt

php -i | grep disable_functions

This should reply with a line that looks like this

disable_functions => no value => no value

But if it returns a string that includes shell_exec, like this (it may contain other content)

disable_functions => shell_exec => shell_exec 

Then you will not be able to continue. The trick at this point is to try a local php.ini file and see if you can turn the offending directive off.

To do this copy the php.ini file to the directory you are working in. Find the disable_functions => shell_exec => shell_exec line remove shell_exec.

then run you script on the command line like this

php -c php.ini myscript.php

However this may all be very restricted on a cloud hosting environment because access to the shell could obviously create a certain amount of chaos.

You can also do this with apache config and .htaccess.

If all the above is OK then check the permissions of testScript.sh and that it is set as executable. To do that is

chmod +x testScript.sh

Sadly for you my bet is that the restricted cloud server environment will stop you.

hayres
  • 120
  • 1
  • 11
  • It turned out that it was a matter of not specifying the interpreter, but thanks for this insight on some of the PHP internals. –  Nov 26 '16 at 07:38
2

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
Ruslan Osmanov
  • 20,486
  • 7
  • 46
  • 60
  • Thanks for the insight this has given me on Linux. Very helpful indeed. –  Nov 26 '16 at 07:41
  • Using your proc_open command I was able to discover that ffmpeg is returning 'Permission denied' however even setting all the privileges/permissions to 744 ffmpeg will still not execute. –  Nov 26 '16 at 09:01
  • @TrueBlue, can you show the code? Otherwise, it's difficult to guess.. By the way, `set -x` command in Bash turns on debugging mode (you can see the commands being executed. – Ruslan Osmanov Nov 26 '16 at 09:03
  • I suspect it is my incompetence. The set -x was useful in telling me that the ffmpeg was not found, so I suspect that simply copying a linux executable onto a web server is not allowed –  Nov 26 '16 at 11:38
  • @TrueBlue, yes, you should install `ffmpeg` package on the server from repository. For example, on Ubuntu: `sudo apt-get install ffmpeg`; on Fedora: `sudo yum install ffmpeg`. – Ruslan Osmanov Nov 26 '16 at 11:50
  • Well I have acquired a little more Linux knowledge over the past day or so thanks to your help. I finally have it all working now and under my CentOS 6 distribution. The key was getting the repository, once I had that the installation went without a hitch. Although this is not part of the initial question, for anyone else with the same issue installing FFMPEG a step by step process is here http://www.crucialp.com/resources/tutorials/server-administration/how-to-install-ffmpeg-centos-rhel-redhat-enterprise-easy-way/ –  Nov 28 '16 at 03:42
0

In shell script must write and the interpretator.

Try this: shell_exec('php ./testScript.sh');

Edit: change php with correct interpretator (bash, sh...)

mr mcwolf
  • 2,574
  • 2
  • 14
  • 27
  • Interesting - yes that fixed it. I am intrigued as to why this solution has not featured in other posts on the this topic. –  Nov 26 '16 at 07:13
  • usually interpreter written in shell script. for example #!/bin/sh (first line in file) – mr mcwolf Nov 26 '16 at 07:20