How I persuaded BILL and ISPmanager Lite 5 to change RAM at a shared hosting tariff
A couple of months ago, for some reasons, I decided to rent a virtual server on Linux and install ISP and BILL on my own to create and manage services.
Having conjured for several hours with documentation and SSH console, I launched my first server on CentOS. Within a week I found out: why gmail.ru and mail.ru do not want to receive letters from my hosting, how to set restrictions on disk space, control php settings for each shared hosting and that BILL, having in its arsenal the ability to purchase additional parameters, including the item "RAM" cannot actually install it.

And the point here is not in BILL itself, namely in ISP Lite - as tech support from ISP System answered me:
The settings of the “RAM” add-on in billing affect the RAM allocated to the user in ISPmanager. But you use ISPmanager Lite, where there are no restrictions on RAM. RAM limitation is available only in ISPmanager Business.
Sadness. Having stuck an hour or two in Google, I did not find anything worthwhile and free. In turn, there is only the possibility to change the parameter with “pens”:
1. By changing the php.ini file in the user’s folder:

2. Open the possibility for the client in ISPmanager to change the PHP parameters independently, which essentially changes the same php.ini file and also at the discretion of the client:

These methods "killed" all the automation of the purchase and maintenance of the hosting. Generally so "not ice." Since I now have my own server, I have the opportunity to "get into" the program, intercept the event and rewrite the treasured item memory_limit in the files to the required value.
Alpha solution
First of all, there was a simple plan: to find the installed data for each user in the bill database and rewrite them in php.ini files with a simple PHP script. And run PHP itself through CRON. But recalling situations when there was not enough 128MB for the site, I understood the following: these cases happened by chance and required almost an instant solution. Making CRON run this script every 5 minutes is too illiterate a solution to the task with idle work 99% of the time.
Beta solution
I began to look for a way to hang a script on the event of changing the additional hosting services. The torment has just begun, since the documentation on the ISPsystem website is not updated at all, which is what the administrators and moderators themselves admit about in their own forum. Googling, I found a way to create an event handler in PHP - which is just magical! Well, in any case, for me, since 90% of my working time is spent writing scripts in this language. The goal was set for the script to be executed immediately after changing additional services by the client in the BILL panel and the restriction value was written to the php.ini file for the current shared hosting. All the work went "by the method of poking, trial and error." As a result, a fairly working way was found to change the values in the INI file at the time of updating the additional shared hosting services in BILLmanager.
The script worked on the event and coped with the task, but what I did not understand was the php-bin folders, and the php.ini file attached to them. Namely: at first these folders were located and worked perfectly along the path / var / www / {user} / data / php-bin / , but after my "bullying" of the ISP and the server as a whole, they changed the location to / var / www / php-bin / {user} / ... According to Google and the aforementioned non-up-documentation from ISP, there is the DisableSecurePhpBin option for this , but it did not affect it in any way. As a result of which, I added to my plugin a search for the php.ini file in both places, as well as a search for a file with the name /var/www/{userasket/data/php-bin/.php.ini (with a dot at the beginning).
What should be done
I won’t write for a long time, I’ll just give ready-made instructions for using my mini-plug-in for BILLmanager 5:
1. You need to create 2 files with root privileges and the following content:
1.1. /usr/local/mgr5/etc/xml/billmgr_mod_hiweb_vhostram.xml
1.2. /usr/local/mgr5/addon/hiweb_vhostram.php
#!/usr/bin/php
query( 'SELECT id FROM pricelist WHERE itemtype=(SELECT id FROM itemtype WHERE name="RAM" AND statparam != "")' );
$priceList = reset( $priceListResult->fetch_assoc() );
///Поиск мегабайт памяти
if(!isset($_SERVER['PARAM_addon_'.$priceList])){
$logInfo[] = 'error: no parameter [PARAM_addon_'.$priceList.'] in $_SERVER';
}else{
$additionMemory = $_SERVER['PARAM_addon_'.$priceList];
///Поиск пользователя
$userLogin = $_SERVER['PARAM_username'];
if( trim( $userLogin ) == '' ){
//do nothing
}
else{
$logInfo[] = 'select user ['.$userLogin.']';
///
//$userResult = $mysql->query( 'SELECT * FROM itemparam WHERE intname="username" AND item="' . $userId . '"' );
//$userData = $userResult->fetch_assoc();
//$userLogin = $userData['value'];
///
///Файлы установок
$phpIniFiles = array(
'/var/www/php-bin/' . $userLogin . '/php.ini', '/var/www/' . $userLogin . '/data/php-bin/.php.ini', '/var/www/' . $userLogin . '/data/php-bin/php.ini'
);
//Перебор файлов
foreach( $phpIniFiles as $phpIni ){
$B = '';
if( !file_exists( $phpIni ) ){
$logInfo[] = 'error: file not exists!';
}elseif( !is_readable( $phpIni ) ){
$logInfo[] = 'error: file not readable!';
}elseif( !is_file( $phpIni ) ){
$logInfo[] = 'error: this is dir, not file!!!';
}else{
$content = file_get_contents( $phpIni );
preg_match('/^memory_limit = (\d){1,4}[a-zA-Z]?$/im',$content, $match);
if(count($match) > 0){
$line = trim(reset($match));
//Получение строки с новыми значениями
$lineExplode = explode( ' = ', $line );
$lineExplode[1] = $additionMemory . 'M';
$newLine = implode( ' = ', $lineExplode );
//Сравнение на изменение и запись в файл новых значений
if( trim( $line ) != trim( $newLine ) ){
$logInfo[] = file_put_contents($phpIni, str_replace($line,$newLine,$content)) ? $line.' → '.$newLine : 'error: file_put_content';
}else{
$logInfo[] = 'not change: '.$line.' → '.$newLine;
}
}else{
$add = 'memory_limit = ' . $additionMemory.'M';
$content .= chr( 13 ) . chr( 10 ) . $add . chr( 13 ) . chr( 10 );
$logInfo[] = file_put_contents($phpIni, $content) ? '+ '.$add : 'error add: file_put_content';
}
}
}
}
}
} else {
$logInfo[] = 'error: mysql not connected!';
}
}
file_put_contents($logFile, print_r( $logInfo, 1 ) );
echo '';
echo ' ';
?>
2. Add an additional option “RAM” to the required tariff - it was available to me immediately after installing ISP, then BILL managers. It remains only to include it in the tariff, indicating a couple of data:


3. It is also necessary to transfer the WWW-domain → PHP to the "CGI" mode of operation:

4. Try to "buy" RAM for virtual hosting in BILLmanager and click "OK":

5. On just in case, a PHP file for checking the work of changing the RAM limit on a shared hosting. Create it in the root of the desired host, next to the index.php file, then call it to check your domain.ru / file.php :
';
echo '' . $memory . ' ';
echo '';
Conclusion
Actual documentation saves a lot of time! )) This plugin is my first experience writing such add-ons and is not a fact that it will work correctly or even work, since I only understand the complexities of Linux and Server software. I think, over time, I will finalize it, if it makes sense.