I had developped a shell script and I wanted to create an UI with it. I decided to use a web interface with a local server because I have few knowledges in HTML/PHP, more than QT or Java. I simply want that my html can run a shell script on my computer.
I have an Apache php server which I start in localhost with apachectl.
In /var/www/html/ I have a shell script and a test_web.php file which execute this script with exec('/var/www/html/test.sh')
In my html I have this:
<form method="POST" action="test_web.php?">
<input type="submit" value="Execute" name="exec">
</form>
If I click on Execute, it opens a new page where I see the output of echo commands from the script but it is not executed on the terminal as a standard script (like if the script is not executed on server side).
I want this script to be executed as started from the terminal.
Thank you for your help
As suggested by some commentators, you could use the Apache cgi features to be able to execute directly your test.sh file (1), but since you say you are using a Php enabled Apache server, you have an alternative and easier option with Php which you partially already tried (2). In both cases, you will need to take care of the permissions and ownership of the bash script, and its execution environment for it to produce the same results as on the command line (3).
1. CGI
CGI stands for Common Gateway Interface. It allows web servers to execute programs that are executable on the host, and interface with the web server. That is a protocol per se, and CGI can be used not only to execute programs, but also for creating dynamic sites. You could program a dynamic website in any language, provided the executable is programmed to receive data via stdin from the server and interpret the headers, decode any contents properly, and that the program can return proper dynamic data to the server via stdout, with proper headers, Content-type, etc.
There are libraries for helping in this task for many languages (for C, Perl has a CGI module in is Core Modules, etc., and even for Bash).
On Linux, to use CGI with Apache 2, you would need to make sure that your Apache configuration loads the required module for supporting it, and select the directory where your web server will be allowed to execute the programs:
# uncomment or add the directive for the module
LoadModule cgid_module modules/mod_cgid.so
# one way to allow the server to execute cgi programs is to
# set a ScriptAlias directive to a directory dedicated to CGI programs
ScriptAlias "/cgi-bin/" "/var/www/html/cgi-bin/"
You put your test.sh script in /var/www/html/cgi-bin/, and browser can be pointed to http://localhost/cgi-bin/test.sh to directly execute the script. There are other configurations possible, see this Apache CGI tuturial.
If you need to execute the Bash program and want your CGI to send anything to the browser, the first echo sent by the Bash script shall be the following output:
Content-type: text/html
followed by whatever dynamic html you want to produce.
2. Php
Really all these complications may not be necessary since you say you use a Php enabled Apache server, and since you probably do not want the Bash script to send html directly to the browser.
In that case, the shell_exec() command or backticks operator, will allow you to run your Bash script and obtain its output in a Php variable, and do whatever you want to do with it in Php.
You say you have tried using the exec command, which should work also, except that you get a status code in response, and not the program output.
If your execution command does not work at all, this may be because of permissions, ownership or execution environment issues.
3. Permissions, ownership and execution environment
Have a look at your Apache logs for errors produced by the exec or shell_exec commands.
The script needs to have execution permissions, and needs to be readable and executable by the web server.
For instance, on Debian, Apache web server runs as a user www-data, so a script would need to be owned and executable by that user:
chown www-data:www-data test.sh
chmod u+x test.sh
You can find the location of the Apache logs and the user and group under which the web server runs in your Apache configuration file by inspecting (as root) the results of:
apachectl -S
Another possible issue is the environment in which Apache will be running the script. That environment, may or not include the same environment variables, the $PATH will be different and may not include all directories available to a "normal" user executing the same script on the console.
Again, check for errors in the logs.
The most frequent cause for failure is a Bash command not found because it is not in the $PATH of the Apache process. The quick fix is then to change the script to prefix the command with its full path.
So, for instance, if your test.sh uses a program called validjson, open your terminal as a user that can execute the script without errors, and check where it is:
$ which validjson
validjson: /usr/local/bin/validjson
and instead of calling validjson in the script assuming it is in the $PATH, call it instead with its full path /usr/local/bin/validjson reported by the which command.
If you are calling other scripts or programs, they may have the same issues, check that until you have debugged the execution of your script.
Related
I'm trying to launch a perl script from within a PHP-based website. In that perl script, I'm using a package, that's installed on a non-standard location. So, to make all packages on that location available without launching perl as "perl -I /path/to/packages", or placing "lib /path/to/packages;" in every perl script I make, I added "/path/to/packages" to the PERL5LIB environmental system variable, and everything works fine when a regular user executes the script. However, when this perl-script is launched from the website, all environmental system variables seem to be inaccessible (tested with $ENV{"PERL5LIB"} and $ENV{"LOGNAME"} in perl, both are uninitialized), causing the perl script to crash because it can't find the required packages in #INC.
How can I make those perl packages available for launch from the website without lauching every perl script with "perl -I /path/to/packages script.pl" and without putting "lib /path/to/packages;" on top of every perl script?
There is two possible way to solve it:
If you own/access the web server, you could add variables globally.
(for apache)
http://www.perlmonks.org/?node_id=844715
<Directory /var/www/>
SetEnv PERL5LIB /your/lib/path
Another workaround that you could setup and maintain your libraries related to script then reach it from your perl script. Please check out FindBin module for this. http://www.perl.com/pub/2002/05/14/mod_perl.html
You could store your script ./bin/, and your libs at ./lib/
If you are using your libs more than one place, you could link it to ./lib/.
#!/usr/bin/perl
use FindBin ();
use lib "$FindBin::Bin../lib/";
use test;
print "test.pm => $INC{'test.pm'}\n";
You have to insure that PER5LIB is set in the environment that your web server launches from.
You'll need to consult the manual for your particular web server to find the configuration command that set environment variables, or you'll need to modify the launcher script (e.g. apachectl) an add the logic to properly set PERL5LIB.
aaaaannnd... somebody was posting examples at the same time I was posting this...
I asked the system admin for help and found out that we're not using apache (as expected) but nginx. That being said, the solution was to add the PERL5LIB definition to the /etc/nginx/fastcgi_params file like this:
sudo echo 'fastcgi_param PERL5LIB "custom/path/to/perl/modules";' >> /etc/nginx/fastcgi_params
sudo service nginx reload
Thank you #LenJaffe and #user1126070 for pointing me in the right direction!
So I'm writing a web server (I know, like the world needs another one!) And I want to call php through CGI. I've got a nice working CGI1.1 implementation good enough to run perl cgi scripts for example.
Now I want to run php. But when my cgi module calls the php program it returns a 404.
How do I get this working?
The details:
I'm running on ubuntu with php5. In my web server, I pass cgi requests to a handler that will find the program and call it with the sc ript as an argument. So here is the code that spawns the cgi process:
chdir( dir );
execve( argv[0], argv.data(), (char* const*) req.posixEnv() );
The command I'm running is equivalent to:
/usr/bin/php5-cgi /home/rafael/webserver/data/cgi-bin/test.php
This means I've set "dir" to:
/home/rafael/webserver/data/cgi-bin
And the cgi process should run in that directory. Argv[0] is "/usr/bin/php5-cgi", argv.data() returns a null terminated array with the following elements:
/usr/bin/php5-cgi
/home/rafael/webserver/data/cgi-bin/test.php
NULL
The process environment contains the CGI environment that includes a block of the usual CGI environment variables.
When I run the above command from a shell, that is by literally typing it into a shell, the script runs fine and php generates the test page. When I call it from CGI it returns:
Status: 404 Not Found
X-Powered-By: PHP/5.3.10-1ubuntu3.2
Content-type: text/html
No input file specified.
Now I know more or less what is happening. PHP is detecting if it is running in CLI or CGI mode, and searching for the script to run differently in each mode. In CGI mode it is probably using CGI environment variables like SCRIPT_FILENAME and DOCUMENT_ROOT to resolve the script name. I've tried a whole bunch of things - different settings for these variables. But none of it works.
What I do know: The whole spawning of PHP, and reading output works. For example if I remove certain CGI variables such that it thinks it is running in CLI mode it works great - generates the page and everything.
What I need to know is:
what is the right way to set up the CGI environment variables for the php-cgi to find my script.
what is the right way to call a php script from exec. I'm using full paths for everything as an effort to debug this. I'd prefer to use relative paths.
All the documentation I can find is about configuring php for cgi on particular web servers. I need to know this from the perspective of someone writing a server.
#EDIT: I have a simpler example that eliminates c++. I'm pretty sure that part is working correctly anyway. Say I make a script that calls php-cgi, and I try to emulate the cgi calling conventions in a shell.
This works:
#export GATEWAY_INTERFACE="CGI/1.1"
export REDIRECT_STATUS=200
export SERVER_PROTOCOL="HTTP/1.1"
export DOCUMENT_ROOT="/home/rafael/web"
#export SCRIPT_FILENAME="cgi-bin/test.php"
export SCRIPT_NAME="cgi-bin/test.php"
/usr/bin/php5-cgi test.php
But this doesn't:
export GATEWAY_INTERFACE="CGI/1.1"
export REDIRECT_STATUS=200
export SERVER_PROTOCOL="HTTP/1.1"
export DOCUMENT_ROOT="/home/rafael/web"
#export SCRIPT_FILENAME="cgi-bin/test.php"
export SCRIPT_NAME="cgi-bin/test.php"
/usr/bin/php5-cgi test.php
I think probably some combination of DOCUMENT_ROOT, SCRIPT_FILENAME and SCRIPT_NAME should work.
The thing that was messing it up was the setting of "doc_root" in php.ini. I unset that like so:
doc_root =
And now cgi environment variables work much more like the CGI spec says. Eg. The following thing now works:
export GATEWAY_INTERFACE="CGI/1.1"
export SERVER_PROTOCOL="HTTP/1.1"
export SCRIPT_FILENAME="/home/rafael/web/cgi-bin/test.php"
export SCRIPT_NAME="test.php"
export REDIRECT_STATUS="200"
/usr/bin/php5-cgi test.php
question is how to give command line (in .cmd script) to execute browser to then in turn have browser execute .php script.
Presently if from a command window I execute like ...
"c:\Program Files\Internet Explorer\iexplore.exe" file:\c:\users\win7ultsdtest\findroot.php
....OR....
C:\Program Files\Internet Explorer\iexplore c:\users\win7ultsdtest\findroot.php
This will run the Explorer browser, but then the browser the browser will download the contents of findroot.php instead of executing the php code as I need. Does anyone know how I can get the browser to instead execute the php code and not just download it as data?
Let me explain my need ... The findroot.php file contains php code to access the $_SERVER['DOCUMENT_ROOT'] variable. This variable is ONLY non-null when the localhost is running a http server and then it contains the localhost document server root path where loadable browser .html, .php etc may be stored to loaded from http:\ lines.
The findroot.php outputs the $_SERVER['DOCUMENT_ROOT'] contents to a file as rootpath.txt so that my .cmd script can then can automatically install PHP code into the active PHP servers document root area.
So understand I must find the $_SERVER['DOCUMENT_ROOT'] from a .cmd script.
Now I might search ALL the computers drives for httpd.conf and then scan that file for the value but this wouldn't work for two reasons; 1. there can be multiple httpd.conf files and I can't know which server is active and using what httpd.conf. 2. it would take a long time to search a given computers entire drive(s) on all httpd.conf files.
The browser won't execute PHP code. You either need a server to run PHP and to access it via HTTP such as C:\Program Files\Internet Explorer\iexplore http://localhost/url/for/findroot.php or you can run PHP via the command line c:\path\to\php.exe c:\users\win7ultsdtest\findroot.php. However running it via the command line won't give you $_SERVER['DOCUMENT_ROOT'] as that is only populated when running PHP within a server.
It's not possible to execute PHP by the HTTP server without the server knowing about the PHP before hand - for example, by being in the document root. Of course if you don't know the document root, your script won't be there. If you're trying to install a script into a web server for a user, it's much better to give instructions on how to do so as their server environment will likely vary from what you expect.
There are light browsers like lynx if you are in a linux machine
lynx http://whateverurl/php.php
I was experimenting with shell_exec and commands, and I can't seem to get this work. Im using the php shell_exec() function and running a screen capture command to take a snapshot of the desktop. When running the script locally through coda, it works fine. Then i ran it through my installion of apache through htdocs, and it runs, yet it doesn't save the image anywhere? For browsers, do i need to change the directory at all? this is what my super simple script looks like. Is this even possible?
<?
$command = "screencapture -iWP ~/Random/test.png";
shell_exec($command);
?>
I don't currently have access to a Mac to test, but I'd be extremely surprised and more than a little concerned if that did work.
On the server, apache should be running under a different user ID to the logged in user, which means the attempt to grab the framebuffer should fail.
If it did at least write (or try to write) an image, then it will be ~/Random/test.png; e.g. if apache runs as a user called apache, the target filename is ~apache/Random/test.png
OSX is basically UNIX, and a key feature of UNIX-like operating systems is security. The video framebuffer should only be accessible to processes running under the UID of the logged in user (or root). Daemon processes like apache httpd should be running under their own, non-root UID.
You probably have to specify the full path of the executable. Also, specifying the full path of the output PNG would help too because they're different users.
Run the command
which screencapture
To find the path that the executable is located in. The output file must be in a writable directory for the user that apache is running under (usually apache). You can check the user that apache is running under by looking in the apache configuration, or just running "top" (as root).
Hope that helps.
I have access to a shared web host.
The website installed there uses exec(). About 4 months ago the function was enabled, but now they have put it on the disable_functions list. They put exec, passthru and shell_exec on that list but they forgot to put system:) This makes me think that the server admin is not very aware on what he's doing. Anyway, they now say that those functions should have never be enabled and they wont re-enable them.
The installed website uses exec() to start some php scripts that would do some background work. Right now i'm looking to see if there is any other "legal" way to start those php scripts in background(i expect system() to work, but maybe they will disable it in the future also).
And now my simple question:
In the perdefined file structure i see a cgi-bin folder. Whats its use? From what i read on the web it is used to generate "dynamic" pages when accessed through the browser, but the server has php anyway installed, so i dont see its use.
/cgi-bin/ is a directory where CGI script should be placed.
You can work around restrictions on exec in PHP by using CGI.
Create a file named somefile.sh with contents:
#!/bin/sh
printf "Content-Type: text/plain\n\n"
#your code here
This will only work if /bin/sh actually exists, and is executable (if you're not in a chroot without /bin/sh for example)
There are enough ways to get a command executed. If they disable CGI, you can continue with SSI.