Here is how to run server.sh from PHP

Disclaimer: This approach is NOT recommended by the ISPConfig developers - as reiterated by Till in many a post. You should only do this in very specific scenarios. I believe that this approach still has its merits however, so I've decided to share my findings in solving this problem with you all.

Server.sh is the shell script that runs server.php which updates all the ISPConfig configuration and does all the useful stuff which happens after you create a client, website, ftp user etc. etc.

Usually server.sh is run by a cron job, as root, every minute

When to use this approach:
We decided to manually invoke server.sh after having used the remoting functions in ISPConfig as we had 2 issues we wanted to solve:

1) Our system setup was time-critical - That is, we wanted ISPConfig to create directories, FTP/DB users immediatly after having called the remoting functions

2) We wanted to avoid creating an extension, if possible, as we wanted to be able to rapidly deploy our system on new servers - and having to mess about with ISPConfig internals and customizing ISPConfig would slow down our deployment process.

Potential pitfalls:
As Till has mentioned then the primary issue with our approach is:

ISPConfig is a multiserver controlpanel, so the controlpanel does not nescessarily run on the same server then the apache webserver. Almost all larger installs use the multiserver features and in these enviroments you can not simply call server.sh from apache.

Click to expand...

The recommended approach is to create an extension which gets invoked after the "regular" server.sh cron job finishes. You can read up on this here:

The solution:
If you have all the potential pitfalls in mind, and still want to run server.sh manually from apache, then here is how to do it. Basically the solution rests in the fact that you can take advantage of the setuid and setgid bits to run a c executable as root. This has been the major stumbling block in running server.sh from apache - as if it isn't run as root, nothing will work (no directories will be created etc. etc. - as the script doesn't run with the appropriate privileges). So what we do is create a c executable which then in turn invokes server.sh

To explain a bit ... The reason you see all that mumbo jumbo regarding a lockfile and not just a straightforward execution of server.sh is that when we were going through this process we ran into a problem with server.sh restarting apache. Usually when ISPConfig adds new vhosts it restarts apache so they are up and running immediatly. For some reason, when we were invoking server.sh from apache this caused the process to hang. I suspect that this is a recursiveness thing - as I could not track down any actual error conditions. That is - calling server.sh from apache which then tries to restart apache hangs, as it is trying to kill itself. So to speak. That's my guess in anyway.

So, we solved this by creating a new cronjob which is run every minute and invoked like so:

/path/to/your/executable/elevaterights restarthttpd

The reference you see to "lockfile" in the above code is just a dummy file which gets copied to .sitekick_lock - which the cron job then looks for to determine whether apache needs a restart.

In addition to this, we had to tweak a bit in the ISPConfig code to stop it from restarting apache when it has done its job. We just added a single line (return 0; ) to the function restartHttpd in server/mods-available/web_module.inc.php (around line 130)

I would be very interested to see if somebody who had another setup were to try the above code - and just removed all the lockfile / manual restart whatnot and see if the same thing happens for them. Because - well as this approach works then the whole apache restart issue makes it slightly messy - and some of the benefit of this approach - which is not altering any ISPConfig files gets slightly lost as we need to do that tweak to web_module.inc.php

Anyhoo - That's my story - Hope this helps someone, and maybe this can spark a discussion on how silly I am in doing all this and that there is a much better approach available (Here's hoping - haha)

If I understand your explanation correctly, you have to restart apache with a one minute cronjob. So your changes get applied after about one minute. Thats the same time that the normal ispconfig system takes to apply the changes, so I dont see the real benefit in the time to get changes applied.

If you want to get changes applied faster, then the approach that was used in ispconfig 2 might be a good choice.

1) Comment out the server.sh root cronjob.
2) create a bash script, e.g. /usr/local/bin/ispconfig_server.sh with the following content:

Start this shell script in the background, it will run forever until you kill it or you reboot the server. It has a very low resource usage. The script checks every 10 seconds if a file /usr/local/ispconfig/interface/web/temp/.run exists and if that file exists it will start the ispconfig update process. You can even reduce the time to less then 10 seconds if nescessary.

So if you want to start an update from the ispconfig interface then, you just execute this php command:

touch('/usr/local/ispconfig/interface/web/temp/.run');

This variant is only usable on single server systems, thats why we dont use it in ispconfig 3.

Thank you for that nice reply and an excellent new approach - I will certainly give it a go as this would probably be a lot cleaner than what I am doing now.

However, one question - The .run file which tells the bash script (ispconfig_server.sh) to invoke server.php - this gets created by ISPConfig whenever an update to its config has been made? You didn't remove this in ISPConfig 3 even though this approach has been deprecated?

Just making sure

Thanks again!

PS: The reason for all this was that it was critical that directories etc. got created ASAP so we could set up our system files immediatly and update databases etc. - That is, a complete setup of the systems. Accessibility to the site was of a secondary concern - so it was OK that apache got restarted a minute later - as at that point everything was ready to go. With the other approach, the user risked having to wait up to 2 minutes+ for everything to finish (And we don't like to keep people waiting, looking at a spinner ) - Now everything is all set up in 30 seconds or less, typically.

With your new/old approach then +10 seconds is AOK by us, and should solve our problems

However, one question - The .run file which tells the bash script (ispconfig_server.sh) to invoke server.php - this gets created by ISPConfig whenever an update to its config has been made? You didn't remove this in ISPConfig 3 even though this approach has been deprecated?

Click to expand...

No, the file does not get created by ispconfig. You can either invoke it the same way that you do it for your approach or you add the line at the end of the remoting index.php file.

I have now spent the day implementing Till's approach and it works like a beaut.

What I've done is create a cron job which runs a small PHP file which checks whether the bash script Till posted is running, and if not starts it. This is to ensure that it always is active (even after a reboot) - I guess you could add it to /etc/init.d but I didn't want to bother with that.

As you can see I placed the bash script in another location than the one Till mentioned, as I want to keep our own stuff outside of ISPConfig dirs. Also, I had to change ownership of the script to root for everything to work properly.

I did not disable the "regular" server.sh cron job, as I saw no reason to. I still want things to work as usual in ISPConfig if we set up a client/vhost manually in the ISPConfig back-end.

All Till's bash script really does is just wait for .run to be touched/created and then do the update. I modded it slightly so that it only waits 5 seconds between each check. I can't see that this tweak should have any detrimental effect.

I still use my elevated rights executable as posted in the original post - but now its job has changed to:
1) touch .run (you need to be root to do this, so it's a problem from apache)
2) Run all my post ISPConfig update actions as root - I changed this to all be located in a custom PHP file which is run by my elevated rights executable - for easier maintenance

Anyway - Here's a happy man signing off as everything is working as it should