Starting mjpg stream from a PHP file with shell_exec - php

I am trying to start the mjpg process from inside a PHP file on my Raspberry Pi. This is the code I am using in the PHP file.
<?php
//this execution does not work, nor does it echo anything if i try and echo it
$cmd = 'mjpg_streamer -i "/usr/local/lib/input_uvc.so -d /dev/video0 -y -r 640x480 -f 10" -o "/usr/local/lib/output_http.so -p 8090 -w /var/www/mjpg_streamer"';
shell_exec($cmd);
?>
<img src = "http://ip:8090/?action=stream" />
The command works if I execute it directly from the shell and the stream also works in this case, but I want the process to start whenever I access the page, which is not happening right now.
What's the mistake?

The mistake is (almost certainly) due to a permission based problem.
More than likely when you execute the mjpg_streamer library from the CLI you're logged in as someone with sudoer permissions or the like, who can easily execute this.
You must realize that the user who will be making the request to execute the mjpg_streamer library will be the same user that owns the instance of Apache handling the request.
In this scenario, the easiest way to troubleshoot this would be to log into the CLI and then su www-data (likely who owns your instance of apache) and check if you can then run it. If you get a permission denied, then you'll need to change how access to that library is granted. Changing ownership of the library is probably not the best bet, but you could likely get away with modifying the group.

Related

How to securely trigger a git pull using a webhook?

I have set up a github webhook to talk to my webserver api (server is apache2). I securely check for the github secret using the encryption of the payload, as specified on their help page.
When a push to master is done on the repo of the web application, a script (deploy.sh) is triggered via <?php exec. If I trigger this script manually, as root, everything is perfect. But of course, the user that triggers the script on normal circumstances is www-data.
My question is what is the best practice for www-data to do a git pull of the new repo? I have mostly discarded doing exec sudo, but maybe that is the way. One problem of the many that i'm facing with making www-data trigger a git pull is that the ~/.ssh/id_rsa file is only set up for root (when building the server image on docker). Its a read-only ssh-key.
This is a legacy application so what really worries me is that through some php exploit someone could do the exec without being github. And from there escalate to get read access to the repo or something worse.
The question is really, what is the best practice to update a web application using a webhook
Solution was allowing www-data to sudo only the deploy command:
echo 'www-data ALL=(ALL) NOPASSWD: /var/my-cool-scripts/deploy.sh' | sudo EDITOR='tee -a' visudo
on php:
exec('sudo -n /var/my-cool-scripts/deploy.sh')
PS: actually used this neat trick to know the execution was okay
$did_the_script_run_okay = exec('sudo -n /var/my-cool-scripts/deploy.sh') == "okay" || false;
last line of deploy.sh:
echo "okay"
the exec command returns the last line echoed by the command, so i check that to ensure complete execution

* failed to open vchiq instance

I try to play sound from a php script to my raspberry pi 3 via the audio jack. I use in the php script the following code:
<?php
$fetch = 'wget "http://192.168.1.127/sound.mp3" -O sound.mp3 --no-check-certificate';
$play = 'omxplayer -o local sound.mp3';
echo shell_exec($fetch);
echo shell_exec("sudo chown upload sound.mp3");
echo shell_exec($play);
?>
I got the file from a local ip adress and save it to the pi. Then I play the sound via the omxplayer command. On the real shell (over SSH in Putty), the Pi will output the sound without any problems. When I try the script, I got the following error message when I use the omxplayer command.
* failed to open vchiq instance
I searched then in forums for this error. They mean that it will be something with the missing permission of the file. For that I set the whole directory to the permission level 777 and the fileowner, as you can see in the script, to upload.
Unfortunately, this didn't work. Does anyone have another solution to get an output from the pi?
Thanks for every responses.
Omxplayer is a video and audio player. Your user needs to be in the video group, even though you only want to playback audio.
Don't use the 777 mode on the /dev/vchiq because it's not secure! A better solution is to add your user to the system group called video. For example:
To add user testuser in your Linux system to the video group, use this command:
usermod -aG video testuser
Finally I found a solution for that problem, after I searched again. The problem was with a directory in the /dev. I hit the following command in the command line and it works great.
sudo chmod 777 /dev/vchiq
A lot of users have actually been brought to this question because they tried raspistill and it returned this error.
In any case, the error is usually because you forgot to add the sudo, so sudo raspistill -o output.jpg should work.

Executing a command line using php shell_exec() for initiating a camera on the server

I am using opencv for initiating the camera on my arch linux. Its getting initiated and works well when I actually do it from the command line on the server itself.
I want to initialize it using php. I tried doing it using shell_exec from PHP.
My PHP file looks like:
<?php
$output=shell_exec('LD_LIBRARY_PATH=usr/local/lib ./a.out 0 2>&1 1>/dev/null');
echo $output;
?>
It gives this output:
ERROR: capture is NULL
I am running this through my windows web browser as a client and the opencv and the related files are on the server that is my arch linux.
I want to start the camera and capture images when I run this php file from the windows web browser, but when executed it throws the error as mentioned.
While this may work when you are SSHed into your server. The webserver user is most likely different than the user you login as. Popular user ids/groups that webservers run as on Linux machines are http, www-data, nobody, and others.
From this point you have two options.
You can make sure the script you are trying to run from PHP (and all of it's children, if any) is able to be run by the webserver user.
You can modify your /etc/sudoers file which gives the webserver user access to elevate permissions for that script only. (NOTE: This potentially opens up security holes so be careful).
To find out what user your webserver runs as execute this: ps aux
Take a look at the output and the first column in the output lists the user that that process is running at. Here's an excerpt of my webserver (nginx) on one of my boxes:
www-data 26852 0.0 0.0 29768 3840 ? S Jun04 0:50 nginx: worker process
You can see that nginx runs with the user www-data here. You can also execute the command with grep to help you find the process quicker. Grep will only show you those lines which match what you send to it. Here's an example: ps aux | grep nginx
Ok now that you know what user the webserver is running as, let's try giving that user access to the script. Let's say your script is foo and is located in /usr/local/bin. You would do the following commands:
chown www-data /usr/local/bin/foo
After changing ownership on the file try to rerun your command again from your PHP page and see if it works.
For completeness I also said you could give your webserver user sudo privileges to that file. To do that you would need to append the following line to the bottom of your /etc/sudoers file:
www-data ALL= NOPASSWD: /usr/local/bin/foo
Then your shell_exec command could switch to this:
shell_exec('sudo /usr/local/bin/foo');
Please keep in mind that doing this would allow your webserver user to run the script as root which is incredibly dangerous in a variety of situations. However, the camera may require elevated permissions to work. I'm not sure what the permissions requirements are on the camera setup you are trying to invoke.
Good luck. Hope this helps!

Can I rip DVDs from a local web app with HandBrake?

I'm building a PHP web application that will run on my machine, and one of its purposes is to call HandBrakeCLI with an exec() or similar call. If I run the command
HandBrakeCLI -i path_to_dvd_drive -o output_file --preset preset_name
from a shell, it works fine. However, when I put the exact same command in an exec() php function (or similar), it doesn't work, and doesn't return anything, aside from a return status of 0. No errors, nothing else.
Is this just a simple permissions issue that I'm not seeing, due to the lack of errors being spit out? Or am I missing something else?
For debugging, try running the command from the console but as the user PHP runs as. Here are some pointers how to find out which user that is.
Then use sudo to run the command as the Apache user. You will probably get more helpful information from that.
try to exec your script using absolute path (type which HandBrakeCLI in terminal to find it) and append 2>&1 to the end of command, like:
exec('HandBrakeCLI -i path_to_dvd_drive -o output_file --preset preset_name 2>&1')
this way if command outputs anything to stderr you will see it.
is handbrake in the path of whatever shell PHP is invoking when it does the exec()? Does whatever account PHP/webserver is running under have access to the directory where handbrak.exe is, and have permission to execute handbrake.exe? Does the webserver account have permissions to access the dvd drive, etc...
Many things to check, and without better diagnostic information, this is about the best you'll be able to get here.

How to run mplayer with audio speaker output from PHP web script on linux?

I am logged in to linux feora 15 distro with username: stackoverflow.
My browser execute in the local system a PHP script to play a music using PHP system("mplayer /tmp/stackoverflow.wav"), passthru("mplayer /tmp/stackoverflow.wav") command. Such as linux command.
As a user stackoverflow i dont hear any audio. But i can see that mplayer /tmp/stackoverflow.wav is running which has duration of 8minutes audio.
My question is: how can i use PHP system("mplayer /tmp/stackoverflow.wav"); to switch user and run the same command, so that i can hear my music with my PHP?
<?php
// for example
switchuser("su stackoverflow password");
system("mplayer /tmp/itworks.wav");
?>
I would like to do the same.
When I try to run mplayer just via shell_ecex(); it does not select pulseaudio for output. Even when I include into the command -ao pulse it doesn't work.
When I try to run the mplayer command with sudo (I added www-data to the sudoers file), mplayer apparently starts playing (according to ressource usage) but there is no output. When I kill the mplayer instance manually the whole sound output is blocked, even when I launch mplayer via the console.
Do you have any tips for me how to run mplayer via PHP?
Edit: I have a solution! My command looks like this:
shell_exec('sudo -u [username] nohup mplayer -slave [mplayer attributes go here] 2> /dev/null > /dev/null &'));
This also stops the php script from waiting for a result from mplayer, so it starts mplayer and continues operation.
The direct answer to your question would be to use sudo, as in
system("sudo -u <username> mplayer /tmp/itworks.wav")
But, I'm not sure this will solve your problem. Firstly, where do you want the sound outputted? The server or the client/browser? The above technique will work on the server. For the browser, you'd need to get the client to load the .wav file as an object or some such and deal with it, presumably via a plugin.
You mention that you can see a running mplayer process though? If you are at the server (or the server and client are on the same physical machine) and you can't hear any output, then there's something else going on. It's possible that the web server process user doesn't have permission to use the audio card, but then I doubt the mplayer process would continue for so long without terminating with "permission denied" error. To figure this out, we'd need more info I guess

Categories