Skip to content
Advertisement

CGI script not executing bash commands such as ‘CP’

I have a web server (apache2) set up to execute files with a .cgi file extension. This works for some commands. However, I need it to copy the file /var/www/on.html to the location of /var/www/a1.html.

I am using Debian Linux. The script is as follows:

#!/bin/bash
echo "Content-type: text/html"
echo "<html><head><title>Light on"
echo "</title>"
echo "<meta http-equiv='refresh' content='1; url=http://86.11.221.243' />"
echo "</head><body>"
echo "$(gpio mode 8 out) #this turns the light on"
echo "$(cp /var/www/on.html /var/www/a1.html)"
echo "</body></html>"

I am using cp to copy a html webpage with a green background to replace a file which has a black background. This is used to indicate the status of the LED a1 (column a row 1).

Advertisement

Answer

echo "$(cp /var/www/on.html /var/www/a1.html)"

The $() is running the command inside the parenthesis and is replaced by the output (to stdout) of that command. A successful cp does not have any output. A failing cp is giving an error message to stderr, not stdout. In both cases the effect is that of echo "" (outputs an empty line, i.e. a single newline), with perhaps an additional side effect of copying the file. And that copy is run as the www-data user (the one running your web server) …. so would fail if /var/www/ is not writable by it (on my system /var/www/ is owned by root:root and is not world writable, so www-data cannot write in it).

So, no need to have echo on that particular cp line. You could replace it with cp /var/www/on.html /var/www/a1.html ; logger cp got $? (but using cp is not very good, see below)

BTW, the cp is not an atomic operation. What would happen if two such CGI processes are running concurrently is not exactly defined. Perhaps you want to force a hard link with ln -f (that is an atomic operation) instead of cp

You could make /var/www/ owned by www-data, or world-writable. In both cases, that is a security hole (which you might afford on a dedicated internal webserver, accessible only from your home network). If you can afford replacing /var/www/on.html and /var/www/a1.html by /var/www/mydir/on.html and /var/www/mydir/a1.html (so change the HTML code refering to them) you could simply have a /var/www/mydir/ directory owned and/or writable by www-data

You could wrap your shell script in a setuid executable (e.g. code a small C program which would execve(2) your script) and chmod u+srx the compiled executable.

You might add (at least to ease debug) some logger(1) command to your script (and/or some syslog(3) to your C program wrapping it), then look into messages under /var/log/

BTW, on a Rasberry Pi, you might replace your apache web server with a dedicated C program (e.g. using some HTTP server library like libonion)

Consider perhaps also AJAX techniques (perhaps combined with websockets) on the browser side.

Advertisement