I was thinking of building a F/OSS project as a cPanel for Ubuntu Server, since Ubuntu doesn't have this, and yet making it easy for a hosting company to use this, where users will find it just as intuitive as cPanel.
Trouble is, PHP web pages on Ubuntu run as
www-data, and lots of senior PHP guys recommend not running a PHP page as
root, and not shelling out and running a Bash script that may have a sticky bit applied on its permissions. They say that's a way to get hacked.
It then dawned on me how to get around this. Make a Bash script daemon in
/etc/init.d that watches a named pipe connection, sitting in a loop. The loop will hang, but that's perfectly okay because it will be in the background, and in a sense it means that the script is dormant and not soaking up CPU cycles. That's cool! It's certainly better than a sleep loop, and means the process only wakes up when there's something that needs to be processed. The sleep loop technique, on the other hand, may be checking for PHP communication when there may not be any, and so the sleep loop soaks up unnecessary CPU. That's why I like the pipe-wait-loop strategy.
So, then all the PHP page has to do is do normal file I/O to like
/tmp/pipe (my pipe, for instance) and the Bash script daemon in the background will wake up out of dormancy in that loop, and process a command as root. It can look in a database for new things it needs to do, and then do those tasks. When done, it can return values to the database and the PHP page can wait in a jQuery/AJAX loop until it receives a response back.
Because the PHP page doesn't actually compose the root commands it needs to run, and merely writes some records to a database table, and sends a string of
"run" to the pipe, it safely passes on a request to the secure daemon in the background.
What do you think of this IPC technique? Good? Bad?
BTW, my demo
/usr/sbin/foo command looks like this. Its point is to demonstrate that
/tmp/foo-was-here was created by the root user account, triggered by a PHP page. It's just the start of something bigger.
#!/bin/bash if [ ! -f /tmp/foo ]; then mkfifo /tmp/foo fi while true; do cat /tmp/foo; touch '/tmp/foo-was-here'; done