SYSADMIN PHP for Sysadmins

Using PHP in administration scripts Delivering Commands Most admins tend to use the shell, , or Python if they need a system administration script. But there is no need for web to learn another language just to script a routine task. PHP gives admins the power to program command-line tools and even complete web inter- faces. BY CARSTEN MÖHRKE www.sxc .hu

HP scripts written for the console PHP tools are typically all you need for parameter is the name of an array, are basically the same as scripts any kind of text manipulation, such as exec() fills the array line by line with Pwritten for the web: programmers modifying configuration files, log files, the output that would have appeared can use the whole range of PHP features. user management entries, and the like. If on screen. If you need to process the To allow simple, program name based ex- you need to access exit code for exec(), you can use the ecution of scripts on the command-line, functions for tasks such as process man- third parameter to do so. you need to specify the PHP interpreter in agement, you will need to add a few • system() does not suppress output, in the first line of the script following #!. If Linux commands. contrast to exec(). It has a second you do not know the path to the inter- optional parameter for the exit code. preter, you can type which to find Command Line • passthru() works like system(), but in out. Also, the script file needs to be exe- PHP has four functions designed for exe- a binary compatible way. This allows cutable. Let’s take a look at the ubi- cuting command lines: exec(), system(), the command to pass images gener- quitous “Hello, World” example in PHP: passthru(), and shell_exec(): ated as converter output to a web • exec() executes the command that is browser. #!/usr/bin/php -q passed to it as the first parameter and • shell_exec() works like the single para- returned as a result. If the second string with the complete command output. The string contains newline Old and New Shell Interface characters, in contrast to the entries in PHP version 4.3.0 or later has a new shell suppress the header by setting the -q the exec() return value array. interface for programming command option when you launch PHP,but this will Both exec() and shell_exec() are useful in line tools: the CLI (Command Line Interface). not remove HTML tags from error cases where you need to manipulate the Previous versions of PHP (and even some messages.) text output from an external command. newer versions) had a program interface You can can check if you have the CGI ver- The following examples use exec(), called Server Application Programmers sion,which does not have the same which is more flexible than the other Interface (SAPI),but SAPI was designed feature-scope as the command-line inter- functions. There is a small glitch for use on web servers (CGI-SAPI) and face, by typing php -v.The examples in this involved with this at present: PHP does added a HTTP header to output. (You can article will work with either version. not always return the external program’s

56 January 2005 www.linux-magazine.com PHP for Sysadmins SYSADMIN

exit code correctly (for example when Table 1: Important ANSI the stream for readability reasons. The concatenating commands). execution time for command-line pro- Sequences grams is not restricted. Process Control Meaning Sequence PHP is ideal for creating web inter- The following PHP script uses exec() to Clear screen \033[2J faces. This attractive option has a few output the number of processes running Cursor to position x,y \033[x;yH hidden pitfalls. When designing the on a system: Cursor n characters left \033[nC application, you need to consider the Cursor n characters up \033[nA potential security risk. The smallest of Font color red \033[0;31m unset ($out); security holes could have fatal conse- Font color black \033[0;30m $cmd="ps axu | wc -l"; quences. An example: Font color green \033[0;32m $erg=exec($cmd,$out); Font color light gray \033[0;37m $erg-=1; //minus 1 line header 01

echo "Number of active U 02 Command:
the string. There is no need to use stdout 03 that will be storing the command output. both commands can be redirected. 04
exec() would not overwrite the array but 05 $outp"; line for the column headings. provide a useful solution, as the shell is 10 } shell_exec() and exec() can only han- capable of interpreting them. These 11 ?> dle data from stdout. To catch standard sequences start with the Escape charac- error output from stderr, you need to ter and are better known as Escape Solutions that will execute arbitrary redirect error output to stdout: 2>&1. sequences. For example, echo "\033[2J" commands (like this one) are out of the Programmers often need to pass com- clears the screen. Table 1 lists a few of question. Administrative scripts should mand-line arguments to a script. To the most important sequences. only be executable within a secure envi- allow this to happen, PHP enters the The selected color stays valid until a ronment, and they should not allow any arguments that follow a filename in the different color is selected. The PHP leeway for manipulation. command line into an array called $argv, ncurses function provides more portabil- keeping the original order. Additionally, ity and a much wider range of features. Special Privileges the number of arguments is stored in the See the examples on the PHP or Zend Scripts often need root privileges. A web- $argc variable. homepages at [2], [3] for more details. based PHP script normally runs with the privileges of the web server user ID. It Good Arguments PHP-based User might seem obvious to give this user – PHP does not support commands that Management typically www, wwwrun, or nobody – read data directly from the keyboard. To The following example demonstrates the more wide-ranging privileges, but this is provide support for keyboard entries, functions referred to thus far in the con- extremely dangerous. Commands like programmers can open the stdin stream text of a script for user management on a sudo or su provide an alternative as a file function and read from the file. server for training purposes. Figure 1 approach. However, su requires the inse- This allows use of the related stdout and shows the menu this code creates. List- cure practice of adding the clear text root stderr streams: ing 1 is just an excerpt, and the complete password to your script. script is available for $in=fopen("php://stdin","r"); download at [4]. $err=fopen("php://stdin","w"); You may note that $input=trim(fgets($fp, 100)); the script opens stan- while (""==$input) dard input with { fopen() but does not fputs($err,"Please input a U use fclose() to close value\n"); it. As PHP automati- } cally closes open streams when the If you use stdin to read keyboard input in program finishes, the this way, your script should trim() the script avoids closing Figure 1:The menu of a PHP script for user management.

www.linux-magazine.com January 2005 57 SYSADMIN PHP for Sysadmins

The sudo tool also can assign root ensures that entries comply with the server user first assumes the identity of privileges for specific actions to a user rules and do not conflict. webadmin temporarily by running su, without that user needing to know the The generic syntax for assigning privi- and is then assigned root privileges for root password. Instead, users authenti- leges with sudo is: WHO WHERE = specific commands via sudo. A script that cate with their own passwords and are WHAT. WHO can be a user name, like in uses this approach might look like this: assigned the privileges specified by root our example, or a group of users, which in the /etc/sudoers file. If an admin needs needs to be defined using User_Alias. $user="webadmin"; //sudoer to assign the webadmin user the right to WHERE means the host where the user $pwd="geheim"; U terminate processes with the kill com- will have these privileges. // Webadmin password mand, he or she could add the following $befehl="kill -9§ § line to /etc/sudoers: Changing Identity ".escapeshellarg($_GET Thanks to the entry in the sudo configu- ["pid"]); webadmin ALL = /bin/kill, U ration file, webadmin can now kill $cmd_line="echo $pwd | U /usr/bin/killall arbitrary processes after entering the su -l $user - password for the user account. An auto- \"echo $pwd | sudo -S U It is a good idea to use the special visudo mated script would stop and prompt for $command 2>&1\""; editor for this. The editor ensures that the password before continuing. There is $ret=shell_exec($cmd_line); only one user can edit the configuration a workaround for this that involves using file at any one time. It additionally sudo’s -S parameter to tell sudo to read The script first uses escape-shellargs() to the password from standard input. The manipulate the pid, which it parses from INFO command line so far is as follows: echo a form. This removes the potential for [1] ANSI codes:http://en.wikipedia.org/wiki/ geheim | sudo -S kill 13221 shell injection attacks, which might oth- ANSI_escape_code If the webadmin user is not the root erwise insert malevolent code. ■ [2] Ncurses function manual:http://www. user of the web server from the php.net/ncurses viewpoint of the processes – this Carsten Möhrke is a freelance consul-

[3] Ncurses tutorial:http://www.zend.com/ would mean scripts inheriting the user’s HOR tant and trainer, the author of T zend/tut/tut-degan.php privileges, which is probably undesirable “Better PHP Programming”,and the CEO of Netviser.You can contact [4] Listing:http://www.linux-magazine.com/ in most cases – you will probably need a Magazine/Downloads/50 Carsten at [email protected]. combination of su and sudo. The web THE AU

Listing 1: PHP Menu 01 #!/usr/bin/php -q 27 { 48 text_black(); 02 25 "-u"==$argv[1] && 47 echo "Administration for 26 isset($argv[2])) user $user\n";

58 January 2005 www.linux-magazine.com