AzoftSpotlightProgramming in PHP for command line

Programming in PHP for command line

By Bogdan Tkachenko on February 6, 2011

Introduction

Ubuntu provides utilities for virtual hosts and modules switch-in\switch-off with apache2 packet. Anyway creating configs for virtual hosts takes additional time. I wanted to improve this shortcoming. I could of course create automatical sub-domains for Apache but I decided to write a script that creates configs of virtual hosts for Apache, and when necessary, it adds the host name into the /etc/hosts file. I’m not very strong in writing scripts in bash, so I decided to use PHP (that I know quite well) for my simple task. This article offers you two interesting things: we will learn the in\output operations for command line in PHP, and write a script that will little bit ease our life.

Access rights checking

It’s not a secret that you need just to write in the first line of PHP script #!/usr/bin/env php and this script can be run as a usual program in Linux. First of all we should check whether we have rights for writing in the folder that keeps configs of virtual hosts, and usually root rights are required for this. It’s very easy to check:


1. $virtual_hosts_dir = "/etc/apache2/sites-available/";
2. if (!is_dir($virtual_hosts_dir) || !is_writable($virtual_hosts_dir))
3. {
4. echo "You must run this script as root!\n";
5. exit;
6. }

Getting information from parameters

Then we need to ask the user for some information that is required for creating the config. Except of sequential input from Console this information can be given as parameters that we give when calling the script. There are global variables $argc and $argv in PHP. The first one contains the number of counted parameters, the second one — an array with counted parameters. By default there is only one counted parameter — full way to the called script. So processing of counted variables is just about processing the array:


1. if ($argc>1)
2. {
3. for ($i=1; $i<$argc; $i++)
4. {
5. $option = explode("=", $argv[$i]);
6. switch ($option[0])
7. {
8. case "-h":
9. case "--add-to-hosts":
10. $add_to_hosts = true;
11. break;
12.
13. case "-n":
14. case "--no-add-to-hosts":
15. $add_to_hosts = false;
16. break;
17.
18. case "-a":
19. case "--server-alias":
20. if (isset($option[1]))
21. {
22. $server_alias = $option[1];
23. }
24. else
25. {
26. echo "Wrong option: {$argv[$i]}\n";
27. }
28. break;
29.
30. case "-d":
31. case "--document-root":
32. if (isset($option[1]))
33. {
34. if ($option[1] == "default")
35. {
36. $document_root = $default_doc_root
37. }
38. else if (is_dir(dirname($option[1])))
39. {
40. $document_root = $option[1];
41. }
42. }
43. else
44. {
45. echo "Wrong option: {$argv[$i]}\n";
46. }
47. break;
48.
49. default:
50. if (substr($argv[$i], 1, 1) == '-')
51. {
52. echo "Unknown option: {$argv[$i]}\n";
53. }
54. break;
55. }
56. }
57. }
58.

In/output lines

Entering tons of parameters in Console is not always convenient. That’s why we ask the user to insert something from the keyboard. In our case we'll need only output line for this purpose. The STDIN, STDOUT, STDERR constants are used in PHP when working with in/output lines. These lines actually are very similar to file lines and it’s same simple to work with them. For instance the string:

1. $line = fgets(STDIN);

will just read the line from Console and will write it down into the $line variable. In this case we didn’t open whether close the line, because PHP does it automatically. But we can open the line manually, and keep it open as long as required. It will work faster if you need to read/write more than one line:


1. $stdin = fopen("php://stdin", "r");
2. $line1 = gets($stdin);
3. $line2 = gets($stdin);
4. fclose($stdin);

In this case we first open the line, read the line, than close it. It’s similar with writing, though I prefer to use simply echo for displaying at the screen. Continue to write our script. Till we have no string that is playing the role of the host name, continue asking the user to type something:


1. while (!$server_alias)
2. {
3. echo "Enter your hostname: ";
4. $server_alias = trim(fgets(STDIN));
5. }

Now ask the user whether you need to add the information about this host into the /etc/hosts, but you should ask it only in the case if this information wasn’t given as a parameter before. As I wrote the script for myself I won’t have any real sites and mostly I will have to add the host into /etc/hosts, that’s why if we don’t write anything but just press Enter this is understood as agreement:


1. if ($add_to_hosts === null)
2. {
3. echo "Add $server_alias to your /etc/hosts ? (Y/N) [Y]: ";
4. $line = trim(fgets(STDIN));
5. if ($line == 'n' || $line == 'N')
6. {
7. $add_to_hosts = false;
8. }
9. else
10. {
11. $add_to_hosts = true;
12. }
13. }


1. if (!$document_root)
2. {
3. $default_doc_root = $default_doc_root.'/'.$server_alias;
4. echo "Enter your document root [$default_doc_root]: ";
5. $line = trim(fgets(STDIN));
6. if ($line && is_dir(dirname($line)))
7. {
8. $document_root = $line;
9. }
10. else
11. {
12. $document_root = $default_doc_root;
13. }
14. }

File configs generation

Collecting information is over at this stage and we have everything what is needed to create the config. Make sure that the site root directory exists, if not – create it:


1. if (!is_dir($document_root))
2. {
3. mkdir($document_root);
4. }


1. if ($add_to_hosts)
2. {
3. $hosts = file_get_contents("/etc/hosts");
4. $hosts .= "127.0.0.1\t$server_alias\n";
5. file_put_contents("/etc/hosts", $hosts);
6. }

So does the template of our config look like:


1. $host_template = << 2.
3. ServerAdmin i@bogus.in
4. ServerAlias $server_alias
5.
6. DocumentRoot $document_root
7.
8. Options Indexes FollowSymLinks MultiViews
9. AllowOverride All
10. Order allow,deny
11. allow from all
12.

13.
14. ErrorLog \${APACHE_LOG_DIR}/$server_alias-error.log;
15. LogLevel warn
16. CustomLog \${APACHE_LOG_DIR}/$server_alias-access.log combined
17.

18. HOST;

Now just write down the config into the file and remind the user that the config must be activated with the help of:


1. file_put_contents("/etc/apache2/sites-available/$server_alias", $host_template);
2. echo "Apache config for this hostname created successfully!
Don't forget to run a2ensite $server_alias\n";

The script is ready. You should save it in the file and don't forget to set the flag +x, so you can run it as a program: chmod +x a2addsite

Usage

Now you can use the script. You can enter the whole information from the Console:
% sudo ./a2addsite
Add test.local to your /etc/hosts? (Y/N) [Y]:
Enter your document root [/home/www/test.local]:
Apache config for this hostname created successfully! Don't forget to run a2ensite test.local

or you can give the whole of partial information to the script in form of parameters when calling:
% sudo ./a2addsite --server-alias=test2.local --add-to-hosts --document-root=default
Apache config for this hostname created successfully! Don't forget to run a2ensite test2.local

Outcome

PHP can be used not only to develop web pages but also for solving small local tasks at computer. I wrote the script for myself and you probably will have a wish to change it for yourself.

Bibliography

More information about in/output lines, as well as about other pecularities of work with Console in PHP can be found on the PHP official web page: Command line usage PHP input/output


Bogdan Tkachenko is Team leader of the Bogus Weber project.