Skip to content

Instantly share code, notes, and snippets.

@killerbees19
Last active July 29, 2023 08:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save killerbees19/d678109e305a07cfb5fbece7f30a9a8f to your computer and use it in GitHub Desktop.
Save killerbees19/d678109e305a07cfb5fbece7f30a9a8f to your computer and use it in GitHub Desktop.
if(Seconds_Behind_Master > 900) RESTART_VSERVER();
#!/bin/bash
set -euf -o pipefail
cd "$(dirname "$0")"
SERVER_HOST="fqdn.example.net"
SERVER_NAME="vXXXXXXXXXXXXXXXX"
SSH_HOST="user@server.internal-network.example.net"
SSH_ARGS="-i ./ssh.key -o ConnectTimeout=10 -o BatchMode=yes"
SSH_COMMAND="mysql --defaults-file=~/.slave.cnf -e 'show slave status \G' | grep -F Seconds_Behind_Master | cut -d : -f 2 | awk '{\$1=\$1};1'"
result=`ssh $SSH_ARGS "$SSH_HOST" -- "$SSH_COMMAND"`
if [[ "$result" != "NULL" && "$result" > 900 ]]
then
echo "Seconds_Behind_Master: $result"
echo ./reboot.php "$SERVER_NAME" "$SERVER_HOST"
fi
#!/usr/bin/php
<?php
if(php_sapi_name() !== 'cli' || $argc !== 3)
{
dbg('Usage: %s <VSERVERNAME> <HOSTNAME>', basename(isset($argv[0]) ? $argv[0] : __file__));
exit(1);
}
define('SCP_USERNAME', '1234567890');
define('SCP_PASSWORD', 'SECRETPASSWORD');
define('SERVER_NAME', $argv[1]);
define('SERVER_HOST', $argv[2]);
define('SHUTDOWN_WAIT', 5);
define('SHUTDOWN_RETRY', 20);
define('SHUTDOWN_LIMIT', 60);
define('START_WAIT', 1);
define('START_LIMIT', 120);
set_error_handler('exception_error_handler'); #error_reporting(-1);
$SCPWebServiceEndUser = new SCPWebServiceEndUser(SCP_USERNAME, SCP_PASSWORD);
$i = 0;
$t = null;
while(true)
{
$state = $SCPWebServiceEndUser->getVServerState(SERVER_NAME);
if($state === 'online')
{
if(!($i++ % SHUTDOWN_RETRY) || $t === null)
{
if($i > SHUTDOWN_LIMIT)
{
dbg(null);
dbg('Time limit of %d seconds reached: Power off server %s!', SHUTDOWN_LIMIT * SHUTDOWN_WAIT, SERVER_NAME);
$SCPWebServiceEndUser->vServerPoweroff(SERVER_NAME);
dbg('Server %s powered off after %d seconds.', SERVER_NAME, time() - $t);
break;
}
else if($t !== null)
{
dbg(null);
}
try
{
dbg('Sending ACPI shutdown signal to server %s!', SERVER_NAME);
$SCPWebServiceEndUser->vServerACPIShutdown(SERVER_NAME);
$t = time();
dbg('Waiting for state update...', false);
}
catch(RuntimeException $e)
{
dbg('SOAP->vServerACPIShutdown(): %s', $e->getMessage());
}
}
sleep(SHUTDOWN_WAIT);
dbg('.', false);
continue;
}
else if($state === 'offline')
{
if($t === null)
{
dbg('Server %s is already stopped.', SERVER_NAME);
}
else
{
dbg(null);
dbg('Server %s successfully stopped after %d seconds.', SERVER_NAME, time() - $t);
}
break;
}
throw new RuntimeException(sprintf('Unsupported state: %s', $state));
}
unset($i, $t);
dbg('Starting server %s!', SERVER_NAME);
$SCPWebServiceEndUser->vServerStart(SERVER_NAME);
dbg('Waiting for online status...', false);
$i = 0;
$t = time();
while(true)
{
$_ = $return = null;
exec('ping -c 1 -n ' . escapeshellarg(SERVER_HOST) . ' 1>/dev/null', $_, $return);
if(!$return)
{
dbg(null);
dbg('Server %s successfully started after %d seconds.', SERVER_NAME, time() - $t);
exit(0);
}
else if($i++ > START_LIMIT)
{
dbg(null);
dbg('Time limit of %d seconds reached: Giving up!', SHUTDOWN_LIMIT * SHUTDOWN_WAIT);
dbg(null);
dbg('--------------------------------------');
dbg(' !!! UNABLE TO CHECK SERVER STATE !!! ');
dbg('--------------------------------------');
exit(1);
}
else if($return !== 1)
{
dbg(null);
dbg('-----------------------------------------------');
dbg(' !!! UNSUPPORTED RESULT FROM PING RECEIVED !!! ');
dbg('-----------------------------------------------');
exit($return);
}
sleep(START_WAIT);
dbg('.', false);
}
class SCPWebServiceEndUser
{
const WSDL = 'https://www.servercontrolpanel.de/WSEndUser?wsdl';
private $soap;
private $username;
private $password;
public function __construct($username, $password)
{
$this->username = $username;
$this->password = $password;
$this->soap = new SOAPClient(self::WSDL);
}
public function getVServerState($name)
{
$result = $this->soap->getVServerState([
'loginName' => $this->username,
'password' => $this->password,
'vserverName' => $name,
]);
return $result->return;
}
public function vServerPoweroff($name)
{
$result = $this->soap->vServerPoweroff([
'loginName' => $this->username,
'password' => $this->password,
'vserverName' => $name,
]);
if($result->return === true)
{
return true;
}
$e = isset($result->return->message) ? new SCPWebServiceEndUserException($result->return->message) : null;
throw new RuntimeException(sprintf('Could not power off vServer %s', $name), null, $e);
}
public function vServerACPIShutdown($name)
{
$result = $this->soap->vServerACPIShutdown([
'loginName' => $this->username,
'password' => $this->password,
'vserverName' => $name,
]);
if($result->return === true)
{
return true;
}
$e = isset($result->return->message) ? new SCPWebServiceEndUserException($result->return->message) : null;
throw new RuntimeException(sprintf('Could not send ACPI shutdown signal to vServer %s', $name), null, $e);
}
public function vServerStart($name)
{
$result = $this->soap->vServerStart([
'loginName' => $this->username,
'password' => $this->password,
'vserverName' => $name,
]);
if($result->return === true)
{
return true;
}
$e = isset($result->return->message) ? new SCPWebServiceEndUserException($result->return->message) : null;
throw new RuntimeException(sprintf('Could not start vServer %s', $name), null, $e);
}
}
class SCPWebServiceEndUserException extends RuntimeException
{
}
function exception_error_handler($severity, $message, $file, $line)
{
if(!(error_reporting() & $severity))
{
return;
}
throw new ErrorException($message, 0, $severity, $file, $line);
}
function dbg($message, $nl = null)
{
$eol = PHP_EOL;
$args = func_get_args();
array_shift($args);
if(is_bool($nl))
{
array_shift($args);
if(!$nl)
{
$eol = '';
}
}
fwrite(STDERR, vsprintf($message . $eol, $args));
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment