migrate shell/helper scripts to symfony/console components
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
abstract class Action
|
||||
{
|
||||
|
||||
protected function __construct($args)
|
||||
{
|
||||
$this->_args = $args;
|
||||
}
|
||||
|
||||
public function getActionName()
|
||||
{
|
||||
return get_called_class();
|
||||
}
|
||||
|
||||
abstract public function run();
|
||||
}
|
||||
@@ -1,456 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli\Action;
|
||||
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\SImExporter;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\Cli\ConfigServicesCmd;
|
||||
|
||||
class ConfigServicesAction extends \Froxlor\Cli\Action
|
||||
{
|
||||
|
||||
public function __construct($args)
|
||||
{
|
||||
parent::__construct($args);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* validates the parsed command line parameters
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function validate()
|
||||
{
|
||||
global $lng;
|
||||
|
||||
$this->checkConfigParam(true);
|
||||
$this->parseConfig();
|
||||
|
||||
require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php';
|
||||
|
||||
include_once FROXLOR_INSTALL_DIR . '/lng/english.lng.php';
|
||||
include_once FROXLOR_INSTALL_DIR . '/lng/lng_references.php';
|
||||
|
||||
if (array_key_exists("import-settings", $this->_args)) {
|
||||
$this->importSettings();
|
||||
}
|
||||
|
||||
if (array_key_exists("create", $this->_args)) {
|
||||
$this->createConfig();
|
||||
} elseif (array_key_exists("apply", $this->_args)) {
|
||||
$this->applyConfig();
|
||||
} elseif (array_key_exists("list-daemons", $this->_args) || array_key_exists("daemon", $this->_args)) {
|
||||
ConfigServicesCmd::printwarn("--list-daemons and --daemon only work together with --apply");
|
||||
}
|
||||
}
|
||||
|
||||
private function importSettings()
|
||||
{
|
||||
if (strtoupper(substr($this->_args["import-settings"], 0, 4)) == 'HTTP') {
|
||||
echo "Settings file seems to be an URL, trying to download" . PHP_EOL;
|
||||
$target = "/tmp/froxlor-import-settings-" . time() . ".json";
|
||||
if (@file_exists($target)) {
|
||||
@unlink($target);
|
||||
}
|
||||
$this->downloadFile($this->_args["import-settings"], $target);
|
||||
$this->_args["import-settings"] = $target;
|
||||
}
|
||||
if (! is_file($this->_args["import-settings"])) {
|
||||
throw new \Exception("Given settings file is not a file");
|
||||
} elseif (! file_exists($this->_args["import-settings"])) {
|
||||
throw new \Exception("Given settings file cannot be found ('" . $this->_args["import-settings"] . "')");
|
||||
} elseif (! is_readable($this->_args["import-settings"])) {
|
||||
throw new \Exception("Given settings file cannot be read ('" . $this->_args["import-settings"] . "')");
|
||||
}
|
||||
$imp_content = file_get_contents($this->_args["import-settings"]);
|
||||
SImExporter::import($imp_content);
|
||||
ConfigServicesCmd::printsucc("Successfully imported settings from '" . $this->_args["import-settings"] . "'");
|
||||
}
|
||||
|
||||
private function createConfig()
|
||||
{
|
||||
$_daemons_config = array(
|
||||
'distro' => ""
|
||||
);
|
||||
|
||||
$config_dir = FROXLOR_INSTALL_DIR . '/lib/configfiles/';
|
||||
// show list of available distro's
|
||||
$distros = glob($config_dir . '*.xml');
|
||||
// tmp array
|
||||
$distributions_select_data = array();
|
||||
|
||||
//set default os.
|
||||
$os_dist = array('ID' => 'bullseye');
|
||||
$os_version = array('0' => '11');
|
||||
$os_default = $os_dist['ID'];
|
||||
|
||||
//read os-release
|
||||
if(file_exists('/etc/os-release')) {
|
||||
$os_dist = parse_ini_file('/etc/os-release', false);
|
||||
if(is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) {
|
||||
$os_version = explode('.',$os_dist['VERSION_ID'])[0];
|
||||
}
|
||||
}
|
||||
|
||||
// read in all the distros
|
||||
foreach ($distros as $_distribution) {
|
||||
// get configparser object
|
||||
$dist = new \Froxlor\Config\ConfigParser($_distribution);
|
||||
// get distro-info
|
||||
$dist_display = $this->getCompleteDistroName($dist);
|
||||
// store in tmp array
|
||||
$distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution)));
|
||||
|
||||
//guess if this is the current distro.
|
||||
$ver = explode('.', $dist->distributionVersion)[0];
|
||||
if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) {
|
||||
$os_default = str_replace(".xml", "", strtolower(basename($_distribution)));
|
||||
}
|
||||
}
|
||||
|
||||
// sort by distribution name
|
||||
ksort($distributions_select_data);
|
||||
|
||||
// list all distributions
|
||||
$mask = "|%-50.50s |%-50.50s |\n";
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
printf($mask, 'dist', 'name');
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
foreach ($distributions_select_data as $name => $filename) {
|
||||
printf($mask, $filename, $name);
|
||||
}
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
echo PHP_EOL;
|
||||
|
||||
while (! in_array($_daemons_config['distro'], $distributions_select_data)) {
|
||||
$_daemons_config['distro'] = ConfigServicesCmd::getInput("choose distribution", $os_default);
|
||||
}
|
||||
|
||||
// go through all services and let user check whether to include it or not
|
||||
$configfiles = new \Froxlor\Config\ConfigParser($config_dir . '/' . $_daemons_config['distro'] . ".xml");
|
||||
$services = $configfiles->getServices();
|
||||
|
||||
foreach ($services as $si => $service) {
|
||||
echo PHP_EOL . "--- " . strtoupper($si) . " ---" . PHP_EOL . PHP_EOL;
|
||||
$_daemons_config[$si] = "";
|
||||
|
||||
$daemons = $service->getDaemons();
|
||||
$mask = "|%-50.50s |%-50.50s |\n";
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
printf($mask, 'value', 'name');
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
$default_daemon = "";
|
||||
foreach ($daemons as $di => $dd) {
|
||||
$title = $dd->title;
|
||||
if ($dd->default) {
|
||||
$default_daemon = $di;
|
||||
$title = $title . " (default)";
|
||||
}
|
||||
printf($mask, $di, $title);
|
||||
}
|
||||
printf($mask, "x", "No " . $si);
|
||||
$daemons['x'] = 'x';
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
echo PHP_EOL;
|
||||
if ($si == 'system') {
|
||||
$_daemons_config[$si] = array();
|
||||
// for the system/other services we need a multiple choice possibility
|
||||
ConfigServicesCmd::println("Select every service you need. Enter empty value when done");
|
||||
$sysservice = "";
|
||||
do {
|
||||
$sysservice = ConfigServicesCmd::getInput("choose service");
|
||||
if (! empty($sysservice)) {
|
||||
$_daemons_config[$si][] = $sysservice;
|
||||
}
|
||||
} while (! empty($sysservice));
|
||||
// add 'cron' as fixed part (doesn't hurt if it exists)
|
||||
if (! in_array('cron', $_daemons_config[$si])) {
|
||||
$_daemons_config[$si][] = 'cron';
|
||||
}
|
||||
} else {
|
||||
// for all others -> only one value
|
||||
while (! array_key_exists($_daemons_config[$si], $daemons)) {
|
||||
$_daemons_config[$si] = ConfigServicesCmd::getInput("choose service", $default_daemon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo PHP_EOL . PHP_EOL;
|
||||
$daemons_config = json_encode($_daemons_config);
|
||||
$output = ConfigServicesCmd::getInput("choose output-filename", "/tmp/froxlor-config-" . date('Ymd') . ".json");
|
||||
file_put_contents($output, $daemons_config);
|
||||
ConfigServicesCmd::printsucc("Successfully generated service-configfile '" . $output . "'");
|
||||
echo PHP_EOL;
|
||||
ConfigServicesCmd::printsucc("You can now apply this config running:" . PHP_EOL . "php " . FROXLOR_INSTALL_DIR . "install/scripts/config-services.php --apply=" . $output);
|
||||
echo PHP_EOL;
|
||||
$proceed = ConfigServicesCmd::getYesNo("Do you want to apply the config now? [y/N]", 0);
|
||||
if ($proceed) {
|
||||
passthru("php " . FROXLOR_INSTALL_DIR . "install/scripts/config-services.php --apply=" . $output);
|
||||
}
|
||||
}
|
||||
|
||||
private function getCompleteDistroName($cparser)
|
||||
{
|
||||
// get distro-info
|
||||
$dist_display = $cparser->distributionName;
|
||||
if ($cparser->distributionCodename != '') {
|
||||
$dist_display .= " " . $cparser->distributionCodename;
|
||||
}
|
||||
if ($cparser->distributionVersion != '') {
|
||||
$dist_display .= " (" . $cparser->distributionVersion . ")";
|
||||
}
|
||||
if ($cparser->deprecated) {
|
||||
$dist_display .= " [deprecated]";
|
||||
}
|
||||
return $dist_display;
|
||||
}
|
||||
|
||||
private function applyConfig()
|
||||
{
|
||||
if (strtoupper(substr($this->_args["apply"], 0, 4)) == 'HTTP') {
|
||||
echo "Config file seems to be an URL, trying to download" . PHP_EOL;
|
||||
$target = "/tmp/froxlor-config-" . time() . ".json";
|
||||
if (@file_exists($target)) {
|
||||
@unlink($target);
|
||||
}
|
||||
$this->downloadFile($this->_args["apply"], $target);
|
||||
$this->_args["apply"] = $target;
|
||||
}
|
||||
if (! is_file($this->_args["apply"])) {
|
||||
throw new \Exception("Given config file is not a file");
|
||||
} elseif (! file_exists($this->_args["apply"])) {
|
||||
throw new \Exception("Given config file cannot be found ('" . $this->_args["apply"] . "')");
|
||||
} elseif (! is_readable($this->_args["apply"])) {
|
||||
throw new \Exception("Given config file cannot be read ('" . $this->_args["apply"] . "')");
|
||||
}
|
||||
|
||||
$config = file_get_contents($this->_args["apply"]);
|
||||
$decoded_config = json_decode($config, true);
|
||||
|
||||
if (array_key_exists("list-daemons", $this->_args)) {
|
||||
$mask = "|%-50.50s |%-50.50s |\n";
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
printf($mask, 'service', 'daemon');
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
foreach ($decoded_config as $service => $daemon) {
|
||||
if (is_array($daemon) && count($daemon) > 0) {
|
||||
foreach ($daemon as $sysdaemon) {
|
||||
printf($mask, $service, $sysdaemon);
|
||||
}
|
||||
} else {
|
||||
if ($daemon == 'x') {
|
||||
$daemon = '--- skipped ---';
|
||||
}
|
||||
printf($mask, $service, $daemon);
|
||||
}
|
||||
}
|
||||
printf($mask, str_repeat("-", 50), str_repeat("-", 50));
|
||||
echo PHP_EOL;
|
||||
exit();
|
||||
}
|
||||
|
||||
$only_daemon = null;
|
||||
if (array_key_exists("daemon", $this->_args)) {
|
||||
$only_daemon = $this->_args['daemon'];
|
||||
}
|
||||
|
||||
if (! empty($decoded_config)) {
|
||||
$config_dir = FROXLOR_INSTALL_DIR . '/lib/configfiles/';
|
||||
$configfiles = new \Froxlor\Config\ConfigParser($config_dir . '/' . $decoded_config['distro'] . ".xml");
|
||||
$services = $configfiles->getServices();
|
||||
$replace_arr = $this->getReplacerArray();
|
||||
|
||||
foreach ($services as $si => $service) {
|
||||
echo PHP_EOL . "--- Configuring: " . strtoupper($si) . " ---" . PHP_EOL . PHP_EOL;
|
||||
if (! isset($decoded_config[$si]) || $decoded_config[$si] == 'x') {
|
||||
ConfigServicesCmd::printwarn("Skipping " . strtoupper($si) . " configuration as desired");
|
||||
continue;
|
||||
}
|
||||
$daemons = $service->getDaemons();
|
||||
foreach ($daemons as $di => $dd) {
|
||||
// check for desired service
|
||||
if (($si != 'system' && $decoded_config[$si] != $di) || (is_array($decoded_config[$si]) && ! in_array($di, $decoded_config[$si]))) {
|
||||
continue;
|
||||
}
|
||||
ConfigServicesCmd::println("Configuring '" . $di . "'");
|
||||
|
||||
if (! empty($only_daemon) && $only_daemon != $di) {
|
||||
ConfigServicesCmd::printwarn("Skipping " . $di . " configuration as desired");
|
||||
continue;
|
||||
}
|
||||
// run all cmds
|
||||
$confarr = $dd->getConfig();
|
||||
foreach ($confarr as $action) {
|
||||
switch ($action['type']) {
|
||||
case "install":
|
||||
ConfigServicesCmd::println("Installing required packages");
|
||||
$result = null;
|
||||
passthru(strtr($action['content'], $replace_arr), $result);
|
||||
if (strlen($result) > 1) {
|
||||
echo $result;
|
||||
}
|
||||
break;
|
||||
case "command":
|
||||
exec(strtr($action['content'], $replace_arr));
|
||||
break;
|
||||
case "file":
|
||||
if (array_key_exists('content', $action)) {
|
||||
ConfigServicesCmd::printwarn("Creating file '" . $action['name'] . "'");
|
||||
file_put_contents($action['name'], trim(strtr($action['content'], $replace_arr)));
|
||||
} elseif (array_key_exists('subcommands', $action)) {
|
||||
foreach ($action['subcommands'] as $fileaction) {
|
||||
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
|
||||
exec(strtr($fileaction['content'], $replace_arr));
|
||||
} elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") {
|
||||
exec(strtr($fileaction['content'], $replace_arr));
|
||||
} elseif ($fileaction['type'] == 'file') {
|
||||
ConfigServicesCmd::printwarn("Creating file '" . $fileaction['name'] . "'");
|
||||
file_put_contents($fileaction['name'], trim(strtr($fileaction['content'], $replace_arr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set is_configured flag
|
||||
Settings::Set('panel.is_configured', '1', true);
|
||||
// run cronjob at the end to ensure configs are all up to date
|
||||
exec('php ' . FROXLOR_INSTALL_DIR . '/scripts/froxlor_master_cronjob.php --force');
|
||||
// and done
|
||||
ConfigServicesCmd::printsucc("All services have been configured");
|
||||
} else {
|
||||
ConfigServicesCmd::printerr("Unable to decode given JSON file");
|
||||
}
|
||||
}
|
||||
|
||||
private function getReplacerArray()
|
||||
{
|
||||
$customer_tmpdir = '/tmp/';
|
||||
if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') {
|
||||
$customer_tmpdir = Settings::Get('system.mod_fcgid_tmpdir');
|
||||
} elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.tmpdir') != '') {
|
||||
$customer_tmpdir = Settings::Get('phpfpm.tmpdir');
|
||||
}
|
||||
|
||||
// try to convert namserver hosts to ip's
|
||||
$ns_ips = "";
|
||||
$known_ns_ips = [];
|
||||
if (Settings::Get('system.nameservers') != '') {
|
||||
$nameservers = explode(',', Settings::Get('system.nameservers'));
|
||||
foreach ($nameservers as $nameserver) {
|
||||
$nameserver = trim($nameserver);
|
||||
// DNS servers might be multi homed; allow transfer from all ip
|
||||
// addresses of the DNS server
|
||||
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
|
||||
// append dot to hostname
|
||||
if (substr($nameserver, - 1, 1) != '.') {
|
||||
$nameserver .= '.';
|
||||
}
|
||||
// ignore invalid responses
|
||||
if (! is_array($nameserver_ips)) {
|
||||
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
|
||||
$nameserver_ips = array(
|
||||
$nameserver
|
||||
);
|
||||
} else {
|
||||
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
|
||||
}
|
||||
if (!empty($ns_ips)) {
|
||||
$ns_ips .= ',';
|
||||
}
|
||||
$ns_ips .= implode(",", $nameserver_ips);
|
||||
}
|
||||
}
|
||||
|
||||
// AXFR server
|
||||
if (Settings::Get('system.axfrservers') != '') {
|
||||
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
|
||||
foreach ($axfrservers as $axfrserver) {
|
||||
if (!in_array(trim($axfrserver), $known_ns_ips)) {
|
||||
if (!empty($ns_ips)) {
|
||||
$ns_ips .= ',';
|
||||
}
|
||||
$ns_ips .= trim($axfrserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Database::needSqlData();
|
||||
$sql = Database::getSqlData();
|
||||
|
||||
$replace_arr = array(
|
||||
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
|
||||
'<SQL_UNPRIVILEGED_PASSWORD>' => $sql['passwd'],
|
||||
'<SQL_DB>' => $sql['db'],
|
||||
'<SQL_HOST>' => $sql['host'],
|
||||
'<SQL_SOCKET>' => isset($sql['socket']) ? $sql['socket'] : null,
|
||||
'<SERVERNAME>' => Settings::Get('system.hostname'),
|
||||
'<SERVERIP>' => Settings::Get('system.ipaddress'),
|
||||
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
|
||||
'<NAMESERVERS_IP>' => $ns_ips,
|
||||
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
|
||||
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
|
||||
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
|
||||
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
|
||||
'<CUSTOMER_TMP>' => \Froxlor\FileDir::makeCorrectDir($customer_tmpdir),
|
||||
'<BASE_PATH>' => \Froxlor\FileDir::makeCorrectDir(FROXLOR_INSTALL_DIR),
|
||||
'<BIND_CONFIG_PATH>' => \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory')),
|
||||
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
|
||||
'<CUSTOMER_LOGS>' => \Froxlor\FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')),
|
||||
'<FPM_IPCDIR>' => \Froxlor\FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
|
||||
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup')
|
||||
);
|
||||
return $replace_arr;
|
||||
}
|
||||
|
||||
private function parseConfig()
|
||||
{
|
||||
define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']);
|
||||
if (! class_exists('\\Froxlor\\Database\\Database')) {
|
||||
throw new \Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?");
|
||||
}
|
||||
if (! file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
|
||||
throw new \Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system.");
|
||||
}
|
||||
}
|
||||
|
||||
private function checkConfigParam($needed = false)
|
||||
{
|
||||
if ($needed) {
|
||||
if (! isset($this->_args["froxlor-dir"])) {
|
||||
$this->_args["froxlor-dir"] = \Froxlor\Froxlor::getInstallDir();
|
||||
} elseif (! is_dir($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given --froxlor-dir parameter is not a directory");
|
||||
} elseif (! file_exists($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
|
||||
} elseif (! is_readable($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function downloadFile($src, $dest)
|
||||
{
|
||||
set_time_limit(0);
|
||||
// This is the file where we save the information
|
||||
$fp = fopen($dest, 'w+');
|
||||
// Here is the file we are downloading, replace spaces with %20
|
||||
$ch = curl_init(str_replace(" ", "%20", $src));
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
// write curl response to file
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
// get curl response
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Cli\Action;
|
||||
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Settings;
|
||||
|
||||
class PhpSessioncleanAction extends \Froxlor\Cli\Action
|
||||
{
|
||||
|
||||
public function __construct($args)
|
||||
{
|
||||
parent::__construct($args);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->validate();
|
||||
|
||||
if ((int) Settings::Get('phpfpm.enabled') == 1) {
|
||||
if (isset($this->_args["max-lifetime"]) && is_numeric($this->_args["max-lifetime"]) && $this->_args["max-lifetime"] > 0) {
|
||||
$this->cleanSessionfiles((int)$this->_args["max-lifetime"]);
|
||||
} else {
|
||||
// use default max-lifetime value
|
||||
$this->cleanSessionfiles();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* validates the parsed command line parameters
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function validate()
|
||||
{
|
||||
global $lng;
|
||||
|
||||
$this->checkConfigParam(true);
|
||||
$this->parseConfig();
|
||||
|
||||
require FROXLOR_INSTALL_DIR . '/lib/tables.inc.php';
|
||||
}
|
||||
|
||||
private function cleanSessionfiles(int $maxlifetime = 1440)
|
||||
{
|
||||
// store paths to clean up
|
||||
$paths_to_clean = [];
|
||||
// get all pool-config directories configured
|
||||
$sel_stmt = Database::prepare("SELECT DISTINCT `config_dir` FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
|
||||
Database::pexecute($sel_stmt);
|
||||
while ($fpmd = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$poolfiles = glob(\Froxlor\FileDir::makeCorrectFile($fpmd['config_dir'] . '/*.conf'));
|
||||
foreach ($poolfiles as $cf) {
|
||||
$contents = file_get_contents($cf);
|
||||
$pattern = preg_quote('session.save_path', '/');
|
||||
$pattern = "/" . $pattern . ".+?\=(.*)/";
|
||||
if (preg_match_all($pattern, $contents, $matches)) {
|
||||
$paths_to_clean[] = \Froxlor\FileDir::makeCorrectDir(trim($matches[1][0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// every path is just needed once
|
||||
$paths_to_clean = array_unique($paths_to_clean);
|
||||
|
||||
if (count($paths_to_clean) > 0) {
|
||||
foreach ($paths_to_clean as $ptc) {
|
||||
// find all files older then maxlifetime and delete them
|
||||
\Froxlor\FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete");
|
||||
}
|
||||
}
|
||||
}
|
||||
private function parseConfig()
|
||||
{
|
||||
define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']);
|
||||
if (!class_exists('\\Froxlor\\Database\\Database')) {
|
||||
throw new \Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?");
|
||||
}
|
||||
if (!file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
|
||||
throw new \Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system.");
|
||||
}
|
||||
}
|
||||
|
||||
private function checkConfigParam($needed = false)
|
||||
{
|
||||
if ($needed) {
|
||||
if (!isset($this->_args["froxlor-dir"])) {
|
||||
$this->_args["froxlor-dir"] = \Froxlor\Froxlor::getInstallDir();
|
||||
} elseif (!is_dir($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given --froxlor-dir parameter is not a directory");
|
||||
} elseif (!file_exists($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
|
||||
} elseif (!is_readable($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli\Action;
|
||||
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Cli\SwitchServerIpCmd;
|
||||
|
||||
class SwitchServerIpAction extends \Froxlor\Cli\Action
|
||||
{
|
||||
|
||||
public function __construct($args)
|
||||
{
|
||||
parent::__construct($args);
|
||||
}
|
||||
|
||||
public function run()
|
||||
{
|
||||
$this->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* validates the parsed command line parameters
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function validate()
|
||||
{
|
||||
$need_config = false;
|
||||
if (array_key_exists("list", $this->_args) || array_key_exists("switch", $this->_args)) {
|
||||
$need_config = true;
|
||||
}
|
||||
|
||||
$this->checkConfigParam($need_config);
|
||||
|
||||
$this->parseConfig();
|
||||
|
||||
if (array_key_exists("list", $this->_args)) {
|
||||
$this->listIPs();
|
||||
}
|
||||
if (array_key_exists("switch", $this->_args)) {
|
||||
$this->switchIPs();
|
||||
}
|
||||
}
|
||||
|
||||
private function listIPs()
|
||||
{
|
||||
$sel_stmt = Database::prepare("SELECT * FROM panel_ipsandports ORDER BY ip ASC, port ASC");
|
||||
Database::pexecute($sel_stmt);
|
||||
$ips = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$mask = "|%-10.10s |%-50.50s | %10.10s |\n";
|
||||
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
|
||||
printf($mask, 'id', 'IP address', 'port');
|
||||
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
|
||||
foreach ($ips as $ipdata) {
|
||||
printf($mask, $ipdata['id'], $ipdata['ip'], $ipdata['port']);
|
||||
}
|
||||
printf($mask, str_repeat("-", 10), str_repeat("-", 50), str_repeat("-", 10));
|
||||
echo PHP_EOL . PHP_EOL;
|
||||
}
|
||||
|
||||
private function switchIPs()
|
||||
{
|
||||
$ip_list = $this->_args['switch'];
|
||||
|
||||
if (empty($ip_list) || is_bool($ip_list)) {
|
||||
throw new \Exception("No parameters given for --switch action.");
|
||||
}
|
||||
|
||||
$ips_to_switch = array();
|
||||
$ip_list = explode(" ", $ip_list);
|
||||
foreach ($ip_list as $ips_combo) {
|
||||
$ip_pair = explode(",", $ips_combo);
|
||||
if (count($ip_pair) != 2) {
|
||||
throw new \Exception("Invalid parameter given for --switch");
|
||||
} else {
|
||||
if (filter_var($ip_pair[0], FILTER_VALIDATE_IP) == false) {
|
||||
throw new \Exception("Invalid source ip address: " . $ip_pair[0]);
|
||||
}
|
||||
if (filter_var($ip_pair[1], FILTER_VALIDATE_IP) == false) {
|
||||
throw new \Exception("Invalid target ip address: " . $ip_pair[1]);
|
||||
}
|
||||
if ($ip_pair[0] == $ip_pair[1]) {
|
||||
throw new \Exception("Source and target ip address are equal");
|
||||
}
|
||||
}
|
||||
$ips_to_switch[] = $ip_pair;
|
||||
}
|
||||
|
||||
if (count($ips_to_switch) > 0) {
|
||||
$check_stmt = Database::prepare("SELECT `id` FROM panel_ipsandports WHERE `ip` = :newip");
|
||||
$upd_stmt = Database::prepare("UPDATE panel_ipsandports SET `ip` = :newip WHERE `ip` = :oldip");
|
||||
|
||||
// system.ipaddress
|
||||
$check_sysip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
|
||||
$check_sysip = Database::pexecute_first($check_sysip_stmt);
|
||||
|
||||
// system.mysql_access_host
|
||||
$check_mysqlip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
|
||||
$check_mysqlip = Database::pexecute_first($check_mysqlip_stmt);
|
||||
|
||||
// system.axfrservers
|
||||
$check_axfrip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
|
||||
$check_axfrip = Database::pexecute_first($check_axfrip_stmt);
|
||||
|
||||
foreach ($ips_to_switch as $ip_pair) {
|
||||
echo "Switching IP \033[1m" . $ip_pair[0] . "\033[0m to IP \033[1m" . $ip_pair[1] . "\033[0m" . PHP_EOL;
|
||||
|
||||
$ip_check = Database::pexecute_first($check_stmt, array(
|
||||
'newip' => $ip_pair[1]
|
||||
));
|
||||
if ($ip_check) {
|
||||
SwitchServerIpCmd::printwarn("Note: " . $ip_pair[0] . " not updated to " . $ip_pair[1] . " - IP already exists in froxlor's database");
|
||||
continue;
|
||||
}
|
||||
|
||||
Database::pexecute($upd_stmt, array(
|
||||
'newip' => $ip_pair[1],
|
||||
'oldip' => $ip_pair[0]
|
||||
));
|
||||
$rows_updated = $upd_stmt->rowCount();
|
||||
|
||||
if ($rows_updated == 0) {
|
||||
SwitchServerIpCmd::printwarn("Note: " . $ip_pair[0] . " not updated to " . $ip_pair[1] . " (possibly no entry found in froxlor database. Use --list to see what IP addresses are added in froxlor");
|
||||
}
|
||||
|
||||
// check whether the system.ipaddress needs updating
|
||||
if ($check_sysip['value'] == $ip_pair[0]) {
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newip WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newip' => $ip_pair[1]
|
||||
));
|
||||
SwitchServerIpCmd::printsucc("Updated system-ipaddress from '" . $ip_pair[0] . "' to '" . $ip_pair[1] . "'");
|
||||
}
|
||||
|
||||
// check whether the system.mysql_access_host needs updating
|
||||
if (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) {
|
||||
$new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']);
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newmysql WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newmysql' => $new_mysqlip
|
||||
));
|
||||
SwitchServerIpCmd::printsucc("Updated mysql_access_host from '" . $check_mysqlip['value'] . "' to '" . $new_mysqlip . "'");
|
||||
}
|
||||
|
||||
// check whether the system.axfrservers needs updating
|
||||
if (strstr($check_axfrip['value'], $ip_pair[0]) !== false) {
|
||||
$new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']);
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newaxfr WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newaxfr' => $new_axfrip
|
||||
));
|
||||
SwitchServerIpCmd::printsucc("Updated axfrservers from '" . $check_axfrip['value'] . "' to '" . $new_axfrip . "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo PHP_EOL;
|
||||
SwitchServerIpCmd::printwarn("*** ATTENTION *** Remember to replace IP addresses in configuration files if used anywhere.");
|
||||
SwitchServerIpCmd::printsucc("IP addresses updated");
|
||||
}
|
||||
|
||||
private function parseConfig()
|
||||
{
|
||||
define('FROXLOR_INSTALL_DIR', $this->_args['froxlor-dir']);
|
||||
if (! class_exists('\\Froxlor\\Database\\Database')) {
|
||||
throw new \Exception("Could not find froxlor's Database class. Is froxlor really installed to '" . FROXLOR_INSTALL_DIR . "'?");
|
||||
}
|
||||
if (! file_exists(FROXLOR_INSTALL_DIR . '/lib/userdata.inc.php')) {
|
||||
throw new \Exception("Could not find froxlor's userdata.inc.php file. You should use this script only with a fully installed and setup froxlor system.");
|
||||
}
|
||||
}
|
||||
|
||||
private function checkConfigParam($needed = false)
|
||||
{
|
||||
if ($needed) {
|
||||
if (! isset($this->_args["froxlor-dir"])) {
|
||||
$this->_args["froxlor-dir"] = \Froxlor\Froxlor::getInstallDir();
|
||||
} elseif (! is_dir($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given --froxlor-dir parameter is not a directory");
|
||||
} elseif (! file_exists($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be found ('" . $this->_args["froxlor-dir"] . "')");
|
||||
} elseif (! is_readable($this->_args["froxlor-dir"])) {
|
||||
throw new \Exception("Given froxlor directory cannot be read ('" . $this->_args["froxlor-dir"] . "')");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2018 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
abstract class CmdLineHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* internal variable for passed arguments
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $args = null;
|
||||
|
||||
/**
|
||||
* Action object read from commandline/config
|
||||
*
|
||||
* @var \Froxlor\Cli\Action
|
||||
*/
|
||||
private $action = null;
|
||||
|
||||
/**
|
||||
* Returns a CmdLineHandler object with given
|
||||
* arguments from command line
|
||||
*
|
||||
* @param int $argc
|
||||
* @param array $argv
|
||||
*
|
||||
* @return CmdLineHandler
|
||||
*/
|
||||
public static function processParameters($argc, $argv)
|
||||
{
|
||||
$me = get_called_class();
|
||||
return new $me($argc, $argv);
|
||||
}
|
||||
|
||||
/**
|
||||
* class constructor, validates the command line parameters
|
||||
* and sets the Action-object if valid
|
||||
*
|
||||
* @param int $argc
|
||||
* @param string[] $argv
|
||||
*
|
||||
* @return null
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function __construct($argc, $argv)
|
||||
{
|
||||
self::$args = $this->parseArgs($argv);
|
||||
$this->action = $this->createAction();
|
||||
$this->action->run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the arguments given via the command line;
|
||||
* three types are supported:
|
||||
* 1.
|
||||
* --parm1 or --parm2=value
|
||||
* 2. -xyz (multiple switches in one) or -a=value
|
||||
* 3. parm1 parm2
|
||||
*
|
||||
* The 1. will be mapped as
|
||||
* ["parm1"] => true, ["parm2"] => "value"
|
||||
* The 2. as
|
||||
* ["x"] => true, ["y"] => true, ["z"] => true, ["a"] => "value"
|
||||
* And the 3. as
|
||||
* [0] => "parm1", [1] => "parm2"
|
||||
*
|
||||
* @param array $argv
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function parseArgs($argv)
|
||||
{
|
||||
array_shift($argv);
|
||||
$o = array();
|
||||
foreach ($argv as $a) {
|
||||
if (substr($a, 0, 2) == '--') {
|
||||
$eq = strpos($a, '=');
|
||||
if ($eq !== false) {
|
||||
$o[substr($a, 2, $eq - 2)] = substr($a, $eq + 1);
|
||||
} else {
|
||||
$k = substr($a, 2);
|
||||
if (! isset($o[$k])) {
|
||||
$o[$k] = true;
|
||||
}
|
||||
}
|
||||
} elseif (substr($a, 0, 1) == '-') {
|
||||
if (substr($a, 2, 1) == '=') {
|
||||
$o[substr($a, 1, 1)] = substr($a, 3);
|
||||
} else {
|
||||
foreach (str_split(substr($a, 1)) as $k) {
|
||||
if (! isset($o[$k])) {
|
||||
$o[$k] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$o[] = $a;
|
||||
}
|
||||
}
|
||||
return $o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an Action-Object for the Action-Handler
|
||||
*
|
||||
* @return \Froxlor\Cli\Action
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function createAction()
|
||||
{
|
||||
|
||||
// Test for help-switch
|
||||
if (empty(self::$args) || array_key_exists("help", self::$args) || array_key_exists("h", self::$args)) {
|
||||
static::printHelp();
|
||||
// end of execution
|
||||
}
|
||||
// check if no unknown parameters are present
|
||||
foreach (self::$args as $arg => $value) {
|
||||
|
||||
if (is_numeric($arg)) {
|
||||
throw new \Exception("Unknown parameter '" . $value . "' in argument list");
|
||||
} elseif (! in_array($arg, static::$params) && ! in_array($arg, static::$switches)) {
|
||||
throw new \Exception("Unknown parameter '" . $arg . "' in argument list");
|
||||
}
|
||||
}
|
||||
|
||||
// set debugger switch
|
||||
if (isset(self::$args["d"]) && self::$args["d"] == true) {
|
||||
// Debugger::getInstance()->setEnabled(true);
|
||||
// Debugger::getInstance()->debug("debug output enabled");
|
||||
}
|
||||
|
||||
return new static::$action_class(self::$args);
|
||||
}
|
||||
|
||||
public static function getInput($prompt = "#", $default = "")
|
||||
{
|
||||
if (! empty($default)) {
|
||||
$prompt .= " [" . $default . "]";
|
||||
}
|
||||
$result = readline($prompt . ":");
|
||||
if (empty($result) && ! empty($default)) {
|
||||
$result = $default;
|
||||
}
|
||||
return mb_strtolower($result);
|
||||
}
|
||||
|
||||
public static function getYesNo($prompt = "#", $default = null)
|
||||
{
|
||||
$value = null;
|
||||
$_v = null;
|
||||
|
||||
while (true) {
|
||||
$_v = self::getInput($prompt);
|
||||
|
||||
if (strtolower($_v) == 'y' || strtolower($_v) == 'yes') {
|
||||
$value = 1;
|
||||
break;
|
||||
} elseif (strtolower($_v) == 'n' || strtolower($_v) == 'no') {
|
||||
$value = 0;
|
||||
break;
|
||||
} else {
|
||||
if ($_v == '' && $default != null) {
|
||||
$value = $default;
|
||||
break;
|
||||
} else {
|
||||
echo "Sorry, response " . $_v . " not understood. Please enter 'yes' or 'no'\n";
|
||||
$value = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public static function println($msg = "")
|
||||
{
|
||||
print $msg . PHP_EOL;
|
||||
}
|
||||
|
||||
private static function printcolor($msg = "", $color = "0")
|
||||
{
|
||||
print "\033[" . $color . "m" . $msg . "\033[0m" . PHP_EOL;
|
||||
}
|
||||
|
||||
public static function printerr($msg = "")
|
||||
{
|
||||
self::printcolor($msg, "31");
|
||||
}
|
||||
|
||||
public static function printsucc($msg = "")
|
||||
{
|
||||
self::printcolor($msg, "32");
|
||||
}
|
||||
|
||||
public static function printwarn($msg = "")
|
||||
{
|
||||
self::printcolor($msg, "33");
|
||||
}
|
||||
}
|
||||
475
lib/Froxlor/Cli/ConfigServices.php
Normal file
475
lib/Froxlor/Cli/ConfigServices.php
Normal file
@@ -0,0 +1,475 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\SImExporter;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Config\ConfigParser;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2022 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
final class ConfigServices extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:config-services');
|
||||
$this->setDescription('Configure system services');
|
||||
$this->addOption('create', 'c', InputOption::VALUE_NONE, 'Create a services list configuration for the --apply option.')
|
||||
->addOption('apply', 'a', InputOption::VALUE_REQUIRED, 'Configure your services by given configuration file. To create one run the command with the --create option.')
|
||||
->addOption('list', 'l', InputOption::VALUE_NONE, 'Output the services that are going to be configured using a given config file (--apply option). No services will be configured.')
|
||||
->addOption('daemon', 'd', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'When used with --apply you can specify one or multiple daemons. These will be the only services that get configured.')
|
||||
->addOption('import-settings', 'i', InputOption::VALUE_REQUIRED, 'Import settings from another froxlor installation. This can be done standalone or in addition to --apply.');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
global $lng;
|
||||
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
include_once Froxlor::getInstallDir() . 'lng/english.lng.php';
|
||||
include_once Froxlor::getInstallDir() . 'lng/lng_references.php';
|
||||
|
||||
$result = self::SUCCESS;
|
||||
|
||||
// import settings if given
|
||||
if ($input->getOption('import-settings')) {
|
||||
$result = $this->importSettings($input, $output);
|
||||
}
|
||||
|
||||
if ($result == self::SUCCESS) {
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
if ($input->getOption('create')) {
|
||||
$result = $this->createConfig($input, $output, $io);
|
||||
} elseif ($input->getOption('apply')) {
|
||||
$result = $this->applyConfig($input, $output, $io);
|
||||
} elseif ($input->getOption('list') || $input->getOption('daemon')) {
|
||||
$output->writeln('<error>Options --list and --daemon only work together with --apply.</>');
|
||||
$result = self::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function createConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
|
||||
{
|
||||
$_daemons_config = array(
|
||||
'distro' => ""
|
||||
);
|
||||
|
||||
$config_dir = Froxlor::getInstallDir() . '/lib/configfiles/';
|
||||
// show list of available distro's
|
||||
$distros = glob($config_dir . '*.xml');
|
||||
// tmp array
|
||||
$distributions_select_data = array();
|
||||
|
||||
//set default os.
|
||||
$os_dist = array('ID' => 'bullseye');
|
||||
$os_version = array('0' => '11');
|
||||
$os_default = $os_dist['ID'];
|
||||
|
||||
//read os-release
|
||||
if (file_exists('/etc/os-release')) {
|
||||
$os_dist = parse_ini_file('/etc/os-release', false);
|
||||
if (is_array($os_dist) && array_key_exists('ID', $os_dist) && array_key_exists('VERSION_ID', $os_dist)) {
|
||||
$os_version = explode('.', $os_dist['VERSION_ID'])[0];
|
||||
}
|
||||
}
|
||||
|
||||
// read in all the distros
|
||||
foreach ($distros as $_distribution) {
|
||||
// get configparser object
|
||||
$dist = new \Froxlor\Config\ConfigParser($_distribution);
|
||||
// get distro-info
|
||||
$dist_display = $this->getCompleteDistroName($dist);
|
||||
// store in tmp array
|
||||
$distributions_select_data[$dist_display] = str_replace(".xml", "", strtolower(basename($_distribution)));
|
||||
|
||||
//guess if this is the current distro.
|
||||
$ver = explode('.', $dist->distributionVersion)[0];
|
||||
if (strtolower($os_dist['ID']) == strtolower($dist->distributionName) && $os_version == $ver) {
|
||||
$os_default = str_replace(".xml", "", strtolower(basename($_distribution)));
|
||||
}
|
||||
}
|
||||
|
||||
// sort by distribution name
|
||||
ksort($distributions_select_data);
|
||||
|
||||
// list all distributions
|
||||
$table_rows = [];
|
||||
$valid_dists = [];
|
||||
foreach ($distributions_select_data as $name => $filename) {
|
||||
$table_rows[] = [$filename, $name];
|
||||
$valid_dists[] = $filename;
|
||||
}
|
||||
$io->table(
|
||||
['ID', 'Distribution'],
|
||||
$table_rows
|
||||
);
|
||||
|
||||
$_daemons_config['distro'] = $io->choice('Choose distribution', $valid_dists, $os_default);
|
||||
|
||||
// go through all services and let user check whether to include it or not
|
||||
$configfiles = new ConfigParser($config_dir . '/' . $_daemons_config['distro'] . ".xml");
|
||||
$services = $configfiles->getServices();
|
||||
|
||||
foreach ($services as $si => $service) {
|
||||
$output->writeln("--- " . strtoupper($si) . " ---");
|
||||
$_daemons_config[$si] = "";
|
||||
|
||||
$daemons = $service->getDaemons();
|
||||
$default_daemon = "";
|
||||
$table_rows = [];
|
||||
$valid_options = [];
|
||||
foreach ($daemons as $di => $dd) {
|
||||
$title = $dd->title;
|
||||
if ($dd->default) {
|
||||
$default_daemon = $di;
|
||||
$title = $title . " (default)";
|
||||
}
|
||||
$table_rows[] = [$di, $title];
|
||||
$valid_options[] = $di;
|
||||
}
|
||||
if ($si != 'system') {
|
||||
$table_rows[] = ['x', 'No'];
|
||||
$valid_options[] = 'x';
|
||||
}
|
||||
$io->table(
|
||||
['Value', 'Name'],
|
||||
$table_rows
|
||||
);
|
||||
|
||||
$daemons['x'] = 'x';
|
||||
if ($si == 'system') {
|
||||
$_daemons_config[$si] = array();
|
||||
// for the system/other services we need a multiple choice possibility
|
||||
$output->writeln("<comment>Select every service you need. Enter empty value when done</>");
|
||||
$sysservice = "";
|
||||
do {
|
||||
$sysservice = $io->ask('Choose service');
|
||||
if (!empty($sysservice)) {
|
||||
$_daemons_config[$si][] = $sysservice;
|
||||
}
|
||||
} while (!empty($sysservice));
|
||||
// add 'cron' as fixed part (doesn't hurt if it exists)
|
||||
if (!in_array('cron', $_daemons_config[$si])) {
|
||||
$_daemons_config[$si][] = 'cron';
|
||||
}
|
||||
} else {
|
||||
// for all others -> only one value
|
||||
$_daemons_config[$si] = $io->choice('Choose service', $valid_options, $default_daemon);
|
||||
}
|
||||
}
|
||||
|
||||
$daemons_config = json_encode($_daemons_config);
|
||||
$output_file = $io->ask("Choose output-filename", "/tmp/froxlor-config-" . date('Ymd') . ".json");
|
||||
file_put_contents($output_file, $daemons_config);
|
||||
$output->writeln("<info>Successfully generated service-configfile '" . $output_file . "'</>");
|
||||
$output->writeln([
|
||||
"",
|
||||
"<info>You can now apply this config running:</>",
|
||||
"php " . Froxlor::getInstallDir() . "bin/froxlor-cli froxlor:config-services --apply=" . $output_file,
|
||||
""
|
||||
]);
|
||||
$proceed = $io->confirm("Do you want to apply the config now?", false);
|
||||
if ($proceed) {
|
||||
passthru("php " . Froxlor::getInstallDir() . "bin/froxlor-cli froxlor:config-services --apply=" . $output_file);
|
||||
}
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function applyConfig(InputInterface $input, OutputInterface $output, SymfonyStyle $io)
|
||||
{
|
||||
$applyFile = $input->getOption('apply');
|
||||
|
||||
if (strtoupper(substr($applyFile, 0, 4)) == 'HTTP') {
|
||||
$output->writeln("Config file seems to be an URL, trying to download");
|
||||
$target = "/tmp/froxlor-config-" . time() . ".json";
|
||||
if (@file_exists($target)) {
|
||||
@unlink($target);
|
||||
}
|
||||
$this->downloadFile($applyFile, $target);
|
||||
$applyFile = $target;
|
||||
}
|
||||
if (!is_file($applyFile)) {
|
||||
$output->writeln('<error>Given config file is not a file</>');
|
||||
return self::INVALID;
|
||||
} elseif (!file_exists($applyFile)) {
|
||||
$output->writeln('<error>Given config file cannot be found (' . $applyFile . ')</>');
|
||||
return self::INVALID;
|
||||
} elseif (!is_readable($applyFile)) {
|
||||
$output->writeln('<error>Given config file cannot be read (' . $applyFile . ')</>');
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
$config = file_get_contents($applyFile);
|
||||
$decoded_config = json_decode($config, true);
|
||||
|
||||
if ($input->getOption('list') != false) {
|
||||
$table_rows = [];
|
||||
foreach ($decoded_config as $service => $daemon) {
|
||||
if (is_array($daemon) && count($daemon) > 0) {
|
||||
foreach ($daemon as $sysdaemon) {
|
||||
$table_rows[] = [$service, $sysdaemon];
|
||||
}
|
||||
} else {
|
||||
if ($daemon == 'x') {
|
||||
$daemon = '--- skipped ---';
|
||||
}
|
||||
$table_rows[] = [$service, $daemon];
|
||||
}
|
||||
}
|
||||
|
||||
$io->table(
|
||||
['Service', 'Selected daemon'],
|
||||
$table_rows
|
||||
);
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
$only_daemon = [];
|
||||
if ($input->getOption('daemon') != false) {
|
||||
$only_daemon = $input->getOption('daemon');
|
||||
}
|
||||
|
||||
if (!empty($decoded_config)) {
|
||||
$config_dir = Froxlor::getInstallDir() . 'lib/configfiles/';
|
||||
$configfiles = new ConfigParser($config_dir . '/' . $decoded_config['distro'] . ".xml");
|
||||
$services = $configfiles->getServices();
|
||||
$replace_arr = $this->getReplacerArray();
|
||||
|
||||
foreach ($services as $si => $service) {
|
||||
$output->writeln("--- Configuring: " . strtoupper($si) . " ---");
|
||||
if (!isset($decoded_config[$si]) || $decoded_config[$si] == 'x') {
|
||||
$output->writeln('<comment>Skipping ' . strtoupper($si) . ' configuration as desired</>');
|
||||
continue;
|
||||
}
|
||||
$daemons = $service->getDaemons();
|
||||
foreach ($daemons as $di => $dd) {
|
||||
// check for desired service
|
||||
if (($si != 'system' && $decoded_config[$si] != $di) || (is_array($decoded_config[$si]) && !in_array($di, $decoded_config[$si]))) {
|
||||
continue;
|
||||
}
|
||||
$output->writeln("Configuring '" . $di . "'");
|
||||
|
||||
if (!empty($only_daemon) && !in_array($di, $only_daemon)) {
|
||||
$output->writeln('<comment>Skipping ' . $di . ' configuration as desired</>');
|
||||
continue;
|
||||
}
|
||||
// run all cmds
|
||||
$confarr = $dd->getConfig();
|
||||
foreach ($confarr as $action) {
|
||||
switch ($action['type']) {
|
||||
case "install":
|
||||
$output->writeln("Installing required packages");
|
||||
$result = null;
|
||||
passthru(strtr($action['content'], $replace_arr), $result);
|
||||
if (strlen($result) > 1) {
|
||||
echo $result;
|
||||
}
|
||||
break;
|
||||
case "command":
|
||||
exec(strtr($action['content'], $replace_arr));
|
||||
break;
|
||||
case "file":
|
||||
if (array_key_exists('content', $action)) {
|
||||
$output->writeln('<comment>Creating file "' . $action['name'] . '"</>');
|
||||
file_put_contents($action['name'], trim(strtr($action['content'], $replace_arr)));
|
||||
} elseif (array_key_exists('subcommands', $action)) {
|
||||
foreach ($action['subcommands'] as $fileaction) {
|
||||
if (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "pre") {
|
||||
exec(strtr($fileaction['content'], $replace_arr));
|
||||
} elseif (array_key_exists('execute', $fileaction) && $fileaction['execute'] == "post") {
|
||||
exec(strtr($fileaction['content'], $replace_arr));
|
||||
} elseif ($fileaction['type'] == 'file') {
|
||||
$output->writeln('<comment>Creating file "' . $fileaction['name'] . '"</>');
|
||||
file_put_contents($fileaction['name'], trim(strtr($fileaction['content'], $replace_arr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// set is_configured flag
|
||||
Settings::Set('panel.is_configured', '1', true);
|
||||
// run cronjob at the end to ensure configs are all up to date
|
||||
exec('php ' . Froxlor::getInstallDir() . 'scripts/froxlor_master_cronjob.php --force');
|
||||
// and done
|
||||
$output->writeln('<info>All services have been configured</>');
|
||||
return self::SUCCESS;
|
||||
} else {
|
||||
$output->writeln('<error>Unable to decode given JSON file</>');
|
||||
return self::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
private function getReplacerArray()
|
||||
{
|
||||
$customer_tmpdir = '/tmp/';
|
||||
if (Settings::Get('system.mod_fcgid') == '1' && Settings::Get('system.mod_fcgid_tmpdir') != '') {
|
||||
$customer_tmpdir = Settings::Get('system.mod_fcgid_tmpdir');
|
||||
} elseif (Settings::Get('phpfpm.enabled') == '1' && Settings::Get('phpfpm.tmpdir') != '') {
|
||||
$customer_tmpdir = Settings::Get('phpfpm.tmpdir');
|
||||
}
|
||||
|
||||
// try to convert namserver hosts to ip's
|
||||
$ns_ips = "";
|
||||
$known_ns_ips = [];
|
||||
if (Settings::Get('system.nameservers') != '') {
|
||||
$nameservers = explode(',', Settings::Get('system.nameservers'));
|
||||
foreach ($nameservers as $nameserver) {
|
||||
$nameserver = trim($nameserver);
|
||||
// DNS servers might be multi homed; allow transfer from all ip
|
||||
// addresses of the DNS server
|
||||
$nameserver_ips = \Froxlor\PhpHelper::gethostbynamel6($nameserver);
|
||||
// append dot to hostname
|
||||
if (substr($nameserver, -1, 1) != '.') {
|
||||
$nameserver .= '.';
|
||||
}
|
||||
// ignore invalid responses
|
||||
if (!is_array($nameserver_ips)) {
|
||||
// act like \Froxlor\PhpHelper::gethostbynamel6() and return unmodified hostname on error
|
||||
$nameserver_ips = array(
|
||||
$nameserver
|
||||
);
|
||||
} else {
|
||||
$known_ns_ips = array_merge($known_ns_ips, $nameserver_ips);
|
||||
}
|
||||
if (!empty($ns_ips)) {
|
||||
$ns_ips .= ',';
|
||||
}
|
||||
$ns_ips .= implode(",", $nameserver_ips);
|
||||
}
|
||||
}
|
||||
|
||||
// AXFR server
|
||||
if (Settings::Get('system.axfrservers') != '') {
|
||||
$axfrservers = explode(',', Settings::Get('system.axfrservers'));
|
||||
foreach ($axfrservers as $axfrserver) {
|
||||
if (!in_array(trim($axfrserver), $known_ns_ips)) {
|
||||
if (!empty($ns_ips)) {
|
||||
$ns_ips .= ',';
|
||||
}
|
||||
$ns_ips .= trim($axfrserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Database::needSqlData();
|
||||
$sql = Database::getSqlData();
|
||||
|
||||
$replace_arr = array(
|
||||
'<SQL_UNPRIVILEGED_USER>' => $sql['user'],
|
||||
'<SQL_UNPRIVILEGED_PASSWORD>' => $sql['passwd'],
|
||||
'<SQL_DB>' => $sql['db'],
|
||||
'<SQL_HOST>' => $sql['host'],
|
||||
'<SQL_SOCKET>' => isset($sql['socket']) ? $sql['socket'] : null,
|
||||
'<SERVERNAME>' => Settings::Get('system.hostname'),
|
||||
'<SERVERIP>' => Settings::Get('system.ipaddress'),
|
||||
'<NAMESERVERS>' => Settings::Get('system.nameservers'),
|
||||
'<NAMESERVERS_IP>' => $ns_ips,
|
||||
'<VIRTUAL_MAILBOX_BASE>' => Settings::Get('system.vmail_homedir'),
|
||||
'<VIRTUAL_UID_MAPS>' => Settings::Get('system.vmail_uid'),
|
||||
'<VIRTUAL_GID_MAPS>' => Settings::Get('system.vmail_gid'),
|
||||
'<SSLPROTOCOLS>' => (Settings::Get('system.use_ssl') == '1') ? 'imaps pop3s' : '',
|
||||
'<CUSTOMER_TMP>' => FileDir::makeCorrectDir($customer_tmpdir),
|
||||
'<BASE_PATH>' => Froxlor::getInstallDir(),
|
||||
'<BIND_CONFIG_PATH>' => FileDir::makeCorrectDir(Settings::Get('system.bindconf_directory')),
|
||||
'<WEBSERVER_RELOAD_CMD>' => Settings::Get('system.apachereload_command'),
|
||||
'<CUSTOMER_LOGS>' => FileDir::makeCorrectDir(Settings::Get('system.logfiles_directory')),
|
||||
'<FPM_IPCDIR>' => FileDir::makeCorrectDir(Settings::Get('phpfpm.fastcgi_ipcdir')),
|
||||
'<WEBSERVER_GROUP>' => Settings::Get('system.httpgroup')
|
||||
);
|
||||
return $replace_arr;
|
||||
}
|
||||
|
||||
private function getCompleteDistroName($cparser)
|
||||
{
|
||||
// get distro-info
|
||||
$dist_display = $cparser->distributionName;
|
||||
if ($cparser->distributionCodename != '') {
|
||||
$dist_display .= " " . $cparser->distributionCodename;
|
||||
}
|
||||
if ($cparser->distributionVersion != '') {
|
||||
$dist_display .= " (" . $cparser->distributionVersion . ")";
|
||||
}
|
||||
if ($cparser->deprecated) {
|
||||
$dist_display .= " [deprecated]";
|
||||
}
|
||||
return $dist_display;
|
||||
}
|
||||
|
||||
private function importSettings(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$importFile = $input->getOption('import-settings');
|
||||
|
||||
if (strtoupper(substr($importFile, 0, 4)) == 'HTTP') {
|
||||
$output->writeln("Settings file seems to be an URL, trying to download");
|
||||
$target = "/tmp/froxlor-import-settings-" . time() . ".json";
|
||||
if (@file_exists($target)) {
|
||||
@unlink($target);
|
||||
}
|
||||
$this->downloadFile($importFile, $target);
|
||||
$importFile = $target;
|
||||
}
|
||||
if (!is_file($importFile)) {
|
||||
$output->writeln('<error>Given settings file is not a file</>');
|
||||
return self::INVALID;
|
||||
} elseif (!file_exists($importFile)) {
|
||||
$output->writeln('<error>Given settings file cannot be found (' . $importFile . ')</>');
|
||||
return self::INVALID;
|
||||
} elseif (!is_readable($importFile)) {
|
||||
$output->writeln('<error>Given settings file cannot be read (' . $importFile . ')</>');
|
||||
return self::INVALID;
|
||||
}
|
||||
$imp_content = file_get_contents($importFile);
|
||||
SImExporter::import($imp_content);
|
||||
$output->writeln("<info>Successfully imported settings from '" . $input->getOption('import-settings') . "'</info>");
|
||||
return self::SUCCESS;
|
||||
}
|
||||
|
||||
private function downloadFile($src, $dest)
|
||||
{
|
||||
set_time_limit(0);
|
||||
// This is the file where we save the information
|
||||
$fp = fopen($dest, 'w+');
|
||||
// Here is the file we are downloading, replace spaces with %20
|
||||
$ch = curl_init(str_replace(" ", "%20", $src));
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 50);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
// write curl response to file
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
// get curl response
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2018 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
class ConfigServicesCmd extends CmdLineHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* list of valid switches
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $switches = array(
|
||||
'h'
|
||||
);
|
||||
|
||||
/**
|
||||
* list of valid parameters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $params = array(
|
||||
'create',
|
||||
'apply',
|
||||
'import-settings',
|
||||
'daemon',
|
||||
'list-daemons',
|
||||
'froxlor-dir',
|
||||
'help'
|
||||
);
|
||||
|
||||
public static $action_class = '\\Froxlor\\Cli\\Action\\ConfigServicesAction';
|
||||
|
||||
public static function printHelp()
|
||||
{
|
||||
self::println("");
|
||||
self::println("Help / command line parameters:");
|
||||
self::println("");
|
||||
// commands
|
||||
self::println("--create\t\tlets you create a services list configuration for the 'apply' command");
|
||||
self::println("");
|
||||
self::println("--apply\t\t\tconfigure your services by given configuration file. To create one run the --create command");
|
||||
self::println("\t\t\tExample: --apply=/path/to/my-config.json or --apply=http://domain.tld/my-config.json");
|
||||
self::println("");
|
||||
self::println("--list-daemons\t\tOutput the services that are going to be configured using a given config file. No services will be configured.");
|
||||
self::println("\t\t\tExample: --apply=/path/to/my-config.json --list-daemons");
|
||||
self::println("");
|
||||
self::println("--daemon\t\tWhen running --apply you can specify a daemon. This will be the only service that gets configured");
|
||||
self::println("\t\t\tExample: --apply=/path/to/my-config.json --daemon=apache24");
|
||||
self::println("");
|
||||
self::println("--import-settings\tImport settings from another froxlor installation. This should be done prior to running --apply or alternatively in the same command together.");
|
||||
self::println("\t\t\tExample: --import-settings=/path/to/Froxlor_settings-[version]-[dbversion]-[date].json or --import-settings=http://domain.tld/Froxlor_settings-[version]-[dbversion]-[date].json");
|
||||
self::println("");
|
||||
self::println("--froxlor-dir\t\tpath to froxlor installation");
|
||||
self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/");
|
||||
self::println("");
|
||||
self::println("--help\t\t\tshow help screen (this)");
|
||||
self::println("");
|
||||
// switches
|
||||
// self::println("-d\t\t\tenable debug output");
|
||||
self::println("-h\t\t\tsame as --help");
|
||||
self::println("");
|
||||
|
||||
die(); // end of execution
|
||||
}
|
||||
}
|
||||
88
lib/Froxlor/Cli/PhpSessionclean.php
Normal file
88
lib/Froxlor/Cli/PhpSessionclean.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\FileDir;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\Database\Database;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2022 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
final class PhpSessionclean extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:php-sessionclean');
|
||||
$this->setDescription('Cleans old php-session files from tmp folder');
|
||||
$this->addArgument('max-lifetime', InputArgument::OPTIONAL, 'The number of seconds after which data will be seen as "garbage" and potentially cleaned up. Defaults to "1440"');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
if ((int) Settings::Get('phpfpm.enabled') == 1) {
|
||||
if ($input->hasArgument('max-lifetime') && is_numeric($input->getArgument('max-lifetime')) && $input->getArgument('max-lifetime') > 0) {
|
||||
$this->cleanSessionfiles((int)$input->getArgument('max-lifetime'));
|
||||
} else {
|
||||
// use default max-lifetime value
|
||||
$this->cleanSessionfiles();
|
||||
}
|
||||
return self::SUCCESS;
|
||||
}
|
||||
// php-fpm not enabled
|
||||
$output->writeln('<comment>PHP-FPM not enabled for this installation.</comment>');
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
private function cleanSessionfiles(int $maxlifetime = 1440)
|
||||
{
|
||||
// store paths to clean up
|
||||
$paths_to_clean = [];
|
||||
// get all pool-config directories configured
|
||||
$sel_stmt = Database::prepare("SELECT DISTINCT `config_dir` FROM `" . TABLE_PANEL_FPMDAEMONS . "`");
|
||||
Database::pexecute($sel_stmt);
|
||||
while ($fpmd = $sel_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$poolfiles = glob(FileDir::makeCorrectFile($fpmd['config_dir'] . '/*.conf'));
|
||||
foreach ($poolfiles as $cf) {
|
||||
$contents = file_get_contents($cf);
|
||||
$pattern = preg_quote('session.save_path', '/');
|
||||
$pattern = "/" . $pattern . ".+?\=(.*)/";
|
||||
if (preg_match_all($pattern, $contents, $matches)) {
|
||||
$paths_to_clean[] = FileDir::makeCorrectDir(trim($matches[1][0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// every path is just needed once
|
||||
$paths_to_clean = array_unique($paths_to_clean);
|
||||
|
||||
if (count($paths_to_clean) > 0) {
|
||||
foreach ($paths_to_clean as $ptc) {
|
||||
// find all files older then maxlifetime and delete them
|
||||
FileDir::safe_exec("find -O3 \"" . $ptc . "\" -ignore_readdir_race -depth -mindepth 1 -name 'sess_*' -type f -cmin \"+" . $maxlifetime . "\" -delete");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2022 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
class PhpSessioncleanCmd extends CmdLineHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* list of valid switches
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $switches = array(
|
||||
'h'
|
||||
);
|
||||
|
||||
/**
|
||||
* list of valid parameters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $params = array(
|
||||
'froxlor-dir',
|
||||
'max-lifetime',
|
||||
'help'
|
||||
);
|
||||
|
||||
public static $action_class = '\\Froxlor\\Cli\\Action\\PhpSessioncleanAction';
|
||||
|
||||
public static function printHelp()
|
||||
{
|
||||
self::println("");
|
||||
self::println("Help / command line parameters:");
|
||||
self::println("");
|
||||
// commands
|
||||
self::println("--froxlor-dir\t\tpath to froxlor installation");
|
||||
self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/");
|
||||
self::println("");
|
||||
self::println("--max-lifetime\t\tThe number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Defaults to '1440'");
|
||||
self::println("\t\t\tExample: --max-lifetime=2000");
|
||||
self::println("");
|
||||
self::println("--help\t\t\tshow help screen (this)");
|
||||
self::println("");
|
||||
// switches
|
||||
self::println("-h\t\t\tsame as --help");
|
||||
self::println("");
|
||||
|
||||
die(); // end of execution
|
||||
}
|
||||
}
|
||||
181
lib/Froxlor/Cli/SwitchServerIp.php
Normal file
181
lib/Froxlor/Cli/SwitchServerIp.php
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Froxlor\Froxlor;
|
||||
use Froxlor\Database\Database;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2022 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
final class SwitchServerIp extends Command
|
||||
{
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('froxlor:switch-server-ip');
|
||||
$this->setDescription('Easily switch IP addresses e.g. after server migration');
|
||||
$this->addOption('switch', 's', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Switch IP-address pair. A pair is separated by comma. For example: --switch=A,B')
|
||||
->addOption('list', 'l', InputOption::VALUE_NONE, 'List all IP addresses currently added for this server in froxlor');
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if (!file_exists(Froxlor::getInstallDir() . '/lib/userdata.inc.php')) {
|
||||
$output->writeln("<error>Could not find froxlor's userdata.inc.php file. You should use this script only with an installed froxlor system.</>");
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
if ($input->getOption('list') == false && $input->getOption('switch') == false) {
|
||||
$output->writeln('<error>Either --list or --switch option must be provided. Nothing to do, exiting.</>');
|
||||
return self::INVALID;
|
||||
}
|
||||
|
||||
$io = new SymfonyStyle($input, $output);
|
||||
|
||||
$result = self::SUCCESS;
|
||||
|
||||
if ($input->getOption('list')) {
|
||||
|
||||
$sel_stmt = Database::prepare("SELECT * FROM panel_ipsandports ORDER BY ip ASC, port ASC");
|
||||
Database::pexecute($sel_stmt);
|
||||
$ips = $sel_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$table_rows = [];
|
||||
foreach ($ips as $ipdata) {
|
||||
$table_rows[] = [$ipdata['id'], $ipdata['ip'], $ipdata['port']];
|
||||
}
|
||||
|
||||
$io->table(
|
||||
['#', 'IP address', 'Port'],
|
||||
$table_rows
|
||||
);
|
||||
}
|
||||
|
||||
if ($input->getOption('switch')) {
|
||||
$result = $this->switchIPs($input, $output);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function switchIPs(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$ip_list = $input->getOption('switch');
|
||||
|
||||
$has_error = false;
|
||||
foreach ($ip_list as $ips_combo) {
|
||||
$ip_pair = explode(",", $ips_combo);
|
||||
if (count($ip_pair) != 2) {
|
||||
$output->writeln('<error>Invalid option parameter, not a valid IP address pair.</>');
|
||||
$has_error = true;
|
||||
} else {
|
||||
if (filter_var($ip_pair[0], FILTER_VALIDATE_IP) == false) {
|
||||
$output->writeln('<error>Invalid source ip address: ' . $ip_pair[0] . '</>');
|
||||
$has_error = true;
|
||||
}
|
||||
if (filter_var($ip_pair[1], FILTER_VALIDATE_IP) == false) {
|
||||
$output->writeln('<error>Invalid target ip address: ' . $ip_pair[1] . '</>');
|
||||
$has_error = true;
|
||||
}
|
||||
if ($ip_pair[0] == $ip_pair[1] && !$has_error) {
|
||||
$output->writeln('<error>Source and target ip address are equal</>');
|
||||
$has_error = true;
|
||||
}
|
||||
}
|
||||
$ips_to_switch[] = $ip_pair;
|
||||
}
|
||||
if ($has_error) {
|
||||
return self::FAILURE;
|
||||
}
|
||||
|
||||
if (count($ips_to_switch) > 0) {
|
||||
$check_stmt = Database::prepare("SELECT `id` FROM panel_ipsandports WHERE `ip` = :newip");
|
||||
$upd_stmt = Database::prepare("UPDATE panel_ipsandports SET `ip` = :newip WHERE `ip` = :oldip");
|
||||
|
||||
// system.ipaddress
|
||||
$check_sysip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
|
||||
$check_sysip = Database::pexecute_first($check_sysip_stmt);
|
||||
|
||||
// system.mysql_access_host
|
||||
$check_mysqlip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
|
||||
$check_mysqlip = Database::pexecute_first($check_mysqlip_stmt);
|
||||
|
||||
// system.axfrservers
|
||||
$check_axfrip_stmt = Database::prepare("SELECT `value` FROM `panel_settings` WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
|
||||
$check_axfrip = Database::pexecute_first($check_axfrip_stmt);
|
||||
|
||||
foreach ($ips_to_switch as $ip_pair) {
|
||||
$output->writeln('Switching IP <comment>' . $ip_pair[0] . '</> to IP <comment>' . $ip_pair[1] . '</>');
|
||||
|
||||
$ip_check = Database::pexecute_first($check_stmt, array(
|
||||
'newip' => $ip_pair[1]
|
||||
));
|
||||
if ($ip_check) {
|
||||
$output->writeln('<error>Note: ' . $ip_pair[0] . ' not updated to ' . $ip_pair[1] . ' - IP already exists in froxlor\'s database</>');
|
||||
continue;
|
||||
}
|
||||
|
||||
Database::pexecute($upd_stmt, array(
|
||||
'newip' => $ip_pair[1],
|
||||
'oldip' => $ip_pair[0]
|
||||
));
|
||||
$rows_updated = $upd_stmt->rowCount();
|
||||
|
||||
if ($rows_updated == 0) {
|
||||
$output->writeln('<error>Note: ' . $ip_pair[0] . ' not updated to ' . $ip_pair[1] . ' (possibly no entry found in froxlor database. Use --list to see what IP addresses are added in froxlor');
|
||||
continue;
|
||||
}
|
||||
|
||||
// check whether the system.ipaddress needs updating
|
||||
if ($check_sysip['value'] == $ip_pair[0]) {
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newip WHERE `settinggroup` = 'system' and `varname` = 'ipaddress'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newip' => $ip_pair[1]
|
||||
));
|
||||
$output->writeln('<info>Updated system-ipaddress from <comment>' . $ip_pair[0] . '</comment> to <comment>' . $ip_pair[1] . '</comment></info>');
|
||||
}
|
||||
|
||||
// check whether the system.mysql_access_host needs updating
|
||||
if (strstr($check_mysqlip['value'], $ip_pair[0]) !== false) {
|
||||
$new_mysqlip = str_replace($ip_pair[0], $ip_pair[1], $check_mysqlip['value']);
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newmysql WHERE `settinggroup` = 'system' and `varname` = 'mysql_access_host'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newmysql' => $new_mysqlip
|
||||
));
|
||||
$output->writeln('<info>Updated mysql_access_host from <comment>' . $check_mysqlip['value'] . '</comment> to <comment>' . $new_mysqlip . '</comment></info>');
|
||||
}
|
||||
|
||||
// check whether the system.axfrservers needs updating
|
||||
if (strstr($check_axfrip['value'], $ip_pair[0]) !== false) {
|
||||
$new_axfrip = str_replace($ip_pair[0], $ip_pair[1], $check_axfrip['value']);
|
||||
$upd2_stmt = Database::prepare("UPDATE `panel_settings` SET `value` = :newaxfr WHERE `settinggroup` = 'system' and `varname` = 'axfrservers'");
|
||||
Database::pexecute($upd2_stmt, array(
|
||||
'newaxfr' => $new_axfrip
|
||||
));
|
||||
$output->writeln('<info>Updated axfr-servers from <comment>' . $check_axfrip['value'] . '</comment> to <comment>' . $new_axfrip . '</comment></info>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output->writeln("");
|
||||
$output->writeln("<comment>*** ATTENTION *** Remember to replace IP addresses in configuration files if used anywhere.</>");
|
||||
$output->writeln("<info>IP addresses updated</>");
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
namespace Froxlor\Cli;
|
||||
|
||||
/**
|
||||
* This file is part of the Froxlor project.
|
||||
* Copyright (c) 2018 the Froxlor Team (see authors).
|
||||
*
|
||||
* For the full copyright and license information, please view the COPYING
|
||||
* file that was distributed with this source code. You can also view the
|
||||
* COPYING file online at http://files.froxlor.org/misc/COPYING.txt
|
||||
*
|
||||
* @copyright (c) the authors
|
||||
* @author Froxlor team <team@froxlor.org> (2018-)
|
||||
* @license GPLv2 http://files.froxlor.org/misc/COPYING.txt
|
||||
* @package Cron
|
||||
*
|
||||
*/
|
||||
class SwitchServerIpCmd extends CmdLineHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* list of valid switches
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $switches = array(
|
||||
'h'
|
||||
);
|
||||
|
||||
/**
|
||||
* list of valid parameters
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $params = array(
|
||||
'switch',
|
||||
'list',
|
||||
'froxlor-dir',
|
||||
'help'
|
||||
);
|
||||
|
||||
public static $action_class = '\\Froxlor\\Cli\\Action\\SwitchServerIpAction';
|
||||
|
||||
public static function printHelp()
|
||||
{
|
||||
self::println("");
|
||||
self::println("Help / command line parameters:");
|
||||
self::println("");
|
||||
// commands
|
||||
self::println("--switch\t\tlets you switch ip-address A with ip-address B");
|
||||
self::println("\t\t\tExample: --switch=A,B");
|
||||
self::println("\t\t\tExample: --switch=\"A1,B1 A2,B2 A3,B3 ...\"");
|
||||
self::println("");
|
||||
self::println("--list\t\t\tshow all currently used ip-addresses in froxlor");
|
||||
self::println("");
|
||||
self::println("--froxlor-dir\t\tpath to froxlor installation");
|
||||
self::println("\t\t\tExample: --froxlor-dir=/var/www/froxlor/");
|
||||
self::println("");
|
||||
self::println("--help\t\t\tshow help screen (this)");
|
||||
self::println("");
|
||||
// switches
|
||||
// self::println("-d\t\t\tenable debug output");
|
||||
self::println("-h\t\t\tsame as --help");
|
||||
self::println("");
|
||||
|
||||
die(); // end of execution
|
||||
}
|
||||
}
|
||||
@@ -111,7 +111,7 @@ class CronConfig
|
||||
// php sessionclean if enabled
|
||||
if ((int) Settings::Get('phpfpm.enabled') == 1) {
|
||||
$cronfile .= "# Look for and purge old sessions every 30 minutes" . PHP_EOL;
|
||||
$cronfile .= "09,39 * * * * root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/scripts/php-sessionclean.php") . " --froxlor-dir=" . escapeshellarg(\Froxlor\Froxlor::getInstallDir()) . " 1> /dev/null" . PHP_EOL;
|
||||
$cronfile .= "09,39 * * * * root " . $binpath . " " . \Froxlor\FileDir::makeCorrectFile(\Froxlor\Froxlor::getInstallDir() . "/bin/froxlor-cli") . " froxlor:php-sessionclean 1> /dev/null" . PHP_EOL;
|
||||
}
|
||||
|
||||
if (\Froxlor\FileDir::isFreeBSD()) {
|
||||
|
||||
Reference in New Issue
Block a user