The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Automated Backup Script Problem

Discussion in 'Data Protection' started by veridical, Feb 23, 2010.

  1. veridical

    veridical Registered

    Joined:
    Feb 23, 2010
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    1
    I have been using the script below to automatically back up all accounts on my reseller plan to a remote server via ftp. The script first accesses the list accounts page in WHM and then individually backs up each account. However, with the latest cpanel release, the it generates an error.

    I read in another thread about adding a required port number for the remote host to the script, however that did not fully solve the problem with retrieving the account information from WHM.

    Can anyone provide input on making this work again? Thanks.

    Code:
    <?php
    
    /*** BEGIN CONFIG ***/
    $reseller = 'resellerurl.com';//your reseller url
    $whmUser = 'reselleruser';//your web host manager user name
    $whmPass = 'resellerpass';//your web host manager password
    $bkUpReseller = true;//backup the reseller account also? 
    $resellerCpTheme = 'x3';//if you want to back up reseller, we need the reseller cpanel theme
    /*
    Destination for the backup...
    $destType = '/';// Home Directory
    $destType = 'ftp';// Remote FTP Server
    $destType = 'passiveftp'; //Remove FTP Server (Passive mode transfer)
    */
    $destType = 'ftp';//^^^
    $destServer = 'ftp.destination.com';//only if $destServer = 'ftp' or 'passiveftp'
    $destUser = 'ftpuser';//only if $destServer = 'ftp' or 'passiveftp'
    $destPass = 'ftppass';//only if $destServer = 'ftp' or 'passiveftp'
    $destEmail = 'email@email.com';//optional; cpanel will send an email when generation is complete
    $logType = 'file';//output a log to 'file' or 'echo' or 'none'(no log)
    $logFileName = 'bkup_full_log.txt';//can include a path too; only makes sense if $logType = 'file'
    $useSsl = false;//if true, requires SSL on your site, or modify this script to use the shared SSL; this hasn't really been tested
    $day = strtolower(date('l'));
    $dst_dir = $day;
    $dir = $dst_dir;
    $conn_id = ftp_connect($destServer) or die("Couldn't connect to $destServer");
    // try to login
    if (@ftp_login($conn_id, $destUser, $destPass))
     {
     echo "Connected as $destUser@$destServer\n";
     
     $ar_files = ftp_nlist($conn_id, $dst_dir);
     //var_dump($ar_files);
     if (is_array($ar_files))
      { // makes sure there are files
      for ($i=0;$i<sizeof($ar_files);$i++)
       { // for each file
       $st_file = basename($ar_files[$i]);
       if($st_file == '.' || $st_file == '..') continue;
       if (ftp_size($conn_id, $dst_dir.'/'.$st_file) == -1)
        { // check if it is a directory
        ftp_rmAll($conn_id,  $dst_dir.'/'.$st_file); // if so, use recursion
        }
       else
        {
        ftp_delete($conn_id,  $dst_dir.'/'.$st_file); // if not, delete the file
        }
       }
      }
     $flag = ftp_rmdir($conn_id, $dst_dir); // delete empty directories
     }
    else
     {
     header ("location : backup_full.php");
     }
     
    if ( @ftp_chdir( $conn_id, $dir ) )
     {
     $original_directory = ftp_pwd( $conn_id );
        // If it is a directory, then change the directory back to the original directory
        ftp_chdir( $conn_id, $original_directory );
     }
    else
     {
     // try to create the directory $dir
     if (ftp_mkdir($conn_id, $dir))
      {
      echo '<p>successfully created '.$dir.'</p>';
      }
     else
      {
      echo '<p>There was a problem while creating '.$dir.'</p>';
      }
     }
    // close the connection
    ftp_close($conn_id);
    /*
    A comma-separated list of domain names to backup;
    Leave blank to backup all domains found in reseller WHM
    If not blank, ONLY the domains listed will be backed up.
    If listed, the domains must be listed EXACTLY like they appear on the
    list accounts page in WHM, i.e. usually without 'www.'
    $domains = 'example1.com,example2.net';
    */
    $domains = '';
    /*** END CONFIG ***/
    /*** BEGIN MAIN ***/
    set_time_limit(0);
    $time_start = getMicroTime();
    if (!extension_loaded('curl')) {
      dl('php_curl.' .PHP_SHLIB_SUFFIX) or die("Could not load curl extension");
    }
    if($useSsl) {
      $protocol = 'https://';
      $cpPort = '2083';
      $whmPort = '2087';
      writeLog("Using SSL.\n");
    }
    else {
      $protocol = 'http://';
      $cpPort = '2082';
      $whmPort = '2086';
      writeLog("Not using SSL.\n");
    } 
    $domains = trim($domains);
    if(!empty($domains)){
      $chkDoms = true;
      $domains = explode(',',$domains);
      foreach($domains as $d){
        $domains[] = trim($d);
      }
    }
    else {
      $chkDoms = false;
      $domains = array();
    }
    //$postFields = urlencode("dest=$destType&server=$destServer&user=$destPass&pass=$destPass&email=$destEmail");
    $postFields = '';
    $postArray = array();
    $postArray['dest'] = $destType;
    $postArray['server'] = $destServer;
    $postArray['user'] = $destUser;
    $postArray['pass'] = $destPass;
    $postArray['email'] = $destEmail;
    $postArray['rdir'] = $day;
    $thingy = '';
    foreach ($postArray as $k=>$v)
    {
      $thingy.= "$k=".utf8_encode($v).'&';
    }
    $postFields = substr($thingy,0,-1);
     
    //get the WHM 'list accounts' page
    writeLog("Retrieving WHM accounts page...\n");
    $acctsPage = getByCurl("$protocol$reseller:$whmPort/scripts/fetchcsv",$whmUser,$whmPass);
    //var_dump($acctsPage);
    $accounts = array();
    $accounts = explode("\n", trim($acctsPage));
    //var_dump($accounts);
    $account_records = array();
    foreach ($accounts as $row) {
     $account_records[] = explode(',', $row);
    }
    writeLog("Parsing accounts...\n");
    //var_dump($account_records);
    //die('here');
    foreach($account_records as $match) {
        $accDom = '';
        $accUser = '';
        $accTheme = '';
        $r = '';
        $fullUrl = '';
        $accDom = strip_tags(trim($match[1]));//domain
        if($chkDoms)
          if(!in_array($accDom,$domains)) continue;
        $accUser = strip_tags(trim($match[3]));//username
        $accTheme = strip_tags(trim($match[14]));//cpanel theme
     
        $fullUrl = "$protocol$accDom:$cpPort/frontend/$accTheme/backup/dofullbackup.html";
        writeLog("Requesting backup of $accDom...\n");
        $r =& getByCurl($fullUrl,$accUser,$whmPass,array('CURLOPT_POST'=>$postFields));
        if($r === false){
          writeLog("Backup request of $accDom caused an unknown error.\n");
        }
        else {
          writeLog("Backup request of $accDom complete.\n");
        }
        //writeLog("\n\n--$accDom--\n\n$r\n\n------\n\n");
    }
    if($bkUpReseller){
      $fullUrl = "$protocol$reseller:$cpPort/frontend/$resellerCpTheme/backup/dofullbackup.html";
      writeLog("Requesting backup of $reseller...\n");
      $r =& getByCurl($fullUrl,$accUser,$whmPass,array('CURLOPT_POST'=>$postFields));
    }
    $time_end = getMicroTime();
    $time = $time_end - $time_start;
    writeLog("Elapsed time: ".round($time,2)." seconds.\n");
    /*** BEGIN FUNCTIONS ***/
    function getByCurl($url, $user = '', $pass = '',$extra = '') {
      global $useSsl;
      $ch = curl_init();
      //tells curl to save result in a variable instead of outputing to page
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_URL, $url);  
      curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
      curl_setopt ($ch, CURLOPT_COOKIEJAR, './cookie.txt');
      curl_setopt ($ch, CURLOPT_FOLLOWLOCATION,1);
      if(!empty($extra) && is_array($extra)){
        foreach($extra as $opt=>$val){
          switch($opt){
            case 'CURLOPT_REFERER':
              curl_setopt($ch,CURLOPT_REFERER,$val);
            break;
            case 'CURLOPT_POST':
            case 'CURLOPT_POSTFIELDS':
              curl_setopt($ch,CURLOPT_POST,1);
              curl_setopt($ch,CURLOPT_POSTFIELDS,$val);
            break;
          }
        }
      }
      if($useSsl){
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
      }
      $result = curl_exec($ch);
      curl_close($ch);
      return $result;
    }
    function writeLog($entry) {
      global $logType,$logFileName;
      $method = strtolower($logType);
      $entry = date('r').' - '.$entry;
     
      if($method == 'file') {
        $fp = fopen($logFileName,'ab');
     fwrite($fp, $entry);
     fclose($fp);
      } elseif($method == 'echo'){
          echo nl2br($entry);//browser
     
          flush();
      }
      return;
    }
    function getMicroTime(){
      list($usec, $sec) = explode(" ",microtime());
      return ((float)$usec + (float)$sec);
    }
    
    $text = file_get_contents('bkup_full_log.txt');
    echo $text;
    $where_form_is="http".($HTTP_SERVER_VARS["HTTPS"]=="on"?"s":"")."://".$SERVER_NAME.strrev(strstr(strrev($PHP_SELF),"/"));
    $message = stripslashes($text);
    mail("email_address","Full Backup Initiated",$message,"from_email_address");
    unlink('bkup_full_log.txt');
    ?> 
    
     
  2. veridical

    veridical Registered

    Joined:
    Feb 23, 2010
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    1
    After some digging in the script, I figured it out...

    Code:
    $acctsPage = getByCurl("$protocol$reseller:$whmPort/scripts/fetchcsv",$whmUser,$whmPass)
    returns an array of the accounts under the given reseller. In the updated Cpanel Release, the array variables are in a different order than before, so when the script continues:
    Code:
    foreach($account_records as $match) {
        $accDom = '';
        $accUser = '';
        $accTheme = '';
        $r = '';
        $fullUrl = '';
        $accDom = strip_tags(trim($match[1]));//domain
        if($chkDoms)
          if(!in_array($accDom,$domains)) continue;
        $accUser = strip_tags(trim($match[3]));//username
        $accTheme = strip_tags(trim($match[14]));//cpanel theme
     
        $fullUrl = "$protocol$accDom:$cpPort/frontend/$accTheme/backup/dofullbackup.html";
    the variables are assigned incorrectly.
    To correct, I changed
    $accDom = strip_tags(trim($match[1])); to> $accDom = strip_tags(trim($match[0]));

    $accUser = strip_tags(trim($match[3])); to $accUser = strip_tags(trim($match[2]));//username

    $accTheme = strip_tags(trim($match[14]));//cpanel theme to $accTheme = strip_tags(trim($match[9]));//cpanel theme

    Additionally, I had to define $destPort = '21'; and add it to the array for the remote connection.

    With those changes, it's back up and running. (Actually, you also have to make it skip the header row, or else you'll get an error, but it doesn't stop the script, so it's not critical.)
     
  3. level11

    level11 Registered

    Joined:
    Apr 27, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    1
    New Cpanel Stable Release Automated Backup Problem

    Does anyone know where to put the port'21' into the array? if so please post the fully finished code here. thanks
     
  4. banditmafiot

    banditmafiot Registered

    Joined:
    May 16, 2010
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    1
    @verdical

    Hi, can you help me with this script if you managed to make it work ?
    I tried what you said but still not works. Can you post the updated/re-coded script again? Thank you.
     
  5. NathanielB

    NathanielB Member

    Joined:
    Apr 5, 2008
    Messages:
    10
    Likes Received:
    0
    Trophy Points:
    1
    Location:
    UK - Kent - Maidstone - PC
    cPanel Access Level:
    Reseller Owner
    Here is the full code for the above, which says its working but I cant work out the format I need to put in as the destination for the backups to go?!

    Code:
    <?php
    /*
    dv at josheli.com
    3/4/2004
    
    What it does:
    It will request cpanel make full backups of all accounts under a reseller.
    It uses cURL, optionally over SSL.
    
    How it works:
    Reads all accounts (domain, cpanel and username specifically) from the listaccts page in WHM
    Uses cUrl over SSL to call the dofullbackup script of cpanel for each account, using the
    account's username and the reseller's password
    
    This script doesn't require cron, but could use it. 
    Cron for Windows:
    http://www.kalab.com/freeware/cron/cron.htm
    
    Instructions:
    1. Make sure you have the curl extension for PHP available
    2. Modify "config" variables below, to suit
    3. From the command prompt:
        >php bkup_full.php
    4. ([Or] Optionally) Set up a cron job to call this script
    5. If you're going to have it ftp somewhere, make sure that server is setup correctly
    6. Since it could take several minutes to generate the backup and ftp it, 
       and you can't have this request script just waiting around trying to 
       figure out if the backup/ftp cycle is complete, it might be beneficial 
       to have another script check for completion, and delete the generated 
       backup if there was success.
    
    */
    
    /*** BEGIN CONFIG ***/
    
    $reseller = 'www.domain.co.uk';//your reseller url
    $whmUser = 'whm username';//your web host manager user name
    $whmPass = 'whm password';//your web host manager password
    $bkUpReseller = true;//backup the reseller account also? (it's not in the listaccts page)
    $resellerCpTheme = 'x';//if you want to back up reseller, we need the reseller cpanel theme
    
    /*
    Destination for the backup...
    
    $destType = '/';// Home Directory
    $destType = 'ftp';// Remote FTP Server
    $destType = 'passiveftp'; //Remove FTP Server (Passive mode transfer)
    */
    $destType = 'ftp';//^^^
    $destServer = 'ftp.domain.co.uk';//only if $destServer = 'ftp' or 'passiveftp'
    $destUser = 'ftp usernam';//only if $destServer = 'ftp' or 'passiveftp'
    $destPass = 'ftp password';//only if $destServer = 'ftp' or 'passiveftp'
    $destEmail = 'email';//optional; cpanel will send an email when generation is complete
    $destRdir = '/public_html/backup/'; // not quite use on the format for this yet (still testing, will update once known)
    $destPort = 21;
    
    $logType = 'echo';//output a log to 'file' or 'echo' or 'none'(no log)
    $logFileName = 'bkup_full_log.txt';//can include a path too; only makes sense if $logType = 'file'
    $useSsl = false;//if true, requires SSL on your site, or modify this script to use the shared SSL; this hasn't really been tested
    
    /*
    A comma-separated list of domain names to backup;
    Leave blank to backup all domains found in reseller WHM
    If not blank, ONLY the domains listed will be backed up.
    If listed, the domains must be listed EXACTLY like they appear on the
    list accounts page in WHM, i.e. usually without 'www.'
    $domains = 'example1.com,example2.net';
    */
    $domains = '';
    
    /*** END CONFIG ***/
    
    /*** BEGIN MAIN ***/
    set_time_limit(0);
    $time_start = getMicroTime();
    
    if (!extension_loaded('curl')) {
      dl('php_curl.' .PHP_SHLIB_SUFFIX) or die("Could not load curl extension");
    }
    
    if($useSsl) {
      $protocol = 'https://';
      $cpPort = '2083';
      $whmPort = '2087';
      writeLog("Using SSL.\n");
    }
    else {
      $protocol = 'http://';
      $cpPort = '2082';
      $whmPort = '2086';
      writeLog("Not using SSL.\n");
    }
    
    $domains = trim($domains);
    if(!empty($domains)){
      $chkDoms = true;
      $domains = explode(',',$domains);
      foreach($domains as $d){
        $domains[] = trim($d);
      }
    }
    else {
      $chkDoms = false;
      $domains = array();
    }
    //$postFields = urlencode("dest=$destType&server=$destServer&user=$destPass&pass=$destPass&email=$destEmail");
    $postFields = '';
    $postArray = array();
    $postArray['dest'] = $destType;
    $postArray['server'] = $destServer;
    $postArray['user'] = $destUser;
    $postArray['pass'] = $destPass;
    $postArray['email'] = $destEmail;
    $postArray['rdir'] = $destRdir;
    $postArray['port'] = $destPort;
    
    $thingy = '';
    foreach ($postArray as $k=>$v)
    {
      $thingy.= "$k=".utf8_encode($v).'&';
    }
    $postFields = substr($thingy,0,-1);
    
    
    //get the WHM 'list accounts' page
    writeLog("Retrieving WHM accounts page...\n");
    $acctsPage = getByCurl("$protocol$reseller:$whmPort/scripts/fetchcsv",$whmUser,$whmPass);
    //var_dump($acctsPage);
    
    $accounts = array();
    
    $accounts = explode("\n", trim($acctsPage));
    
    //var_dump($accounts);
    
    $account_records = array();
    
    foreach ($accounts as $row) {
            $account_records[] = explode(',', $row);
    }
    
    writeLog("Parsing accounts...\n");
    
    //var_dump($account_records);
    
    //die('here');
    
    foreach($account_records as $match) {
    
        $accDom = '';
        $accUser = '';
        $accTheme = '';
        $r = '';
        $fullUrl = '';
    
        //$accDom = strip_tags(trim($match[1]));//domain - replaced with below
        $accDom = strip_tags(trim($match[0]));//domain
        if($chkDoms)
          if(!in_array($accDom,$domains)) continue;
        //$accUser = strip_tags(trim($match[3]));//username - replaced with below
        $accUser = strip_tags(trim($match[2]));//username
        //$accTheme = strip_tags(trim($match[14]));//cpanel theme - replaced with below
        $accTheme = strip_tags(trim($match[9]));//cpanel theme
    
        $fullUrl = "$protocol$accDom:$cpPort/frontend/$accTheme/backup/dofullbackup.html";
        writeLog("Requesting backup of $accDom...\n");
        $r =& getByCurl($fullUrl,$accUser,$whmPass,array('CURLOPT_POST'=>$postFields));
        if($r === false){
          writeLog("Backup request of $accDom caused an unknown error.\n");
        }
        else {
          writeLog("Backup request of $accDom complete.\n");
        }
        //writeLog("\n\n--$accDom--\n\n$r\n\n------\n\n");
    
    }
    
    if($bkUpReseller){
      $fullUrl = "$protocol$reseller:$cpPort/frontend/$resellerCpTheme/backup/dofullbackup.html";
      writeLog("Requesting backup of $reseller...\n");
      $r =& getByCurl($fullUrl,$accUser,$whmPass,array('CURLOPT_POST'=>$postFields));
    }
    
    $time_end = getMicroTime();
    $time = $time_end - $time_start;
    writeLog("Elapsed time: ".round($time,2)." seconds.\n");
    
    /*** BEGIN FUNCTIONS ***/
    
    function getByCurl($url, $user = '', $pass = '',$extra = '') {
      global $useSsl;
    
      $ch = curl_init();
      //tells curl to save result in a variable instead of outputing to page
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
      curl_setopt ($ch, CURLOPT_COOKIEJAR, './cookie.txt');
      //curl_setopt ($ch, CURLOPT_FOLLOWLOCATION,1); //need safe_mode turning off for this bit
      if(!empty($extra) && is_array($extra)){
        foreach($extra as $opt=>$val){
          switch($opt){
            case 'CURLOPT_REFERER':
              curl_setopt($ch,CURLOPT_REFERER,$val);
            break;
            case 'CURLOPT_POST':
            case 'CURLOPT_POSTFIELDS':
              curl_setopt($ch,CURLOPT_POST,1);
              curl_setopt($ch,CURLOPT_POSTFIELDS,$val);
            break;
          }
        }
      }
      if($useSsl){
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
      }
      $result = curl_exec($ch);
      curl_close($ch);
    
      return $result;
    }
    
    function writeLog($entry) {
      global $logType,$logFileName;
    
      $method = strtolower($logType);
    
      $entry = date('r').' - '.$entry;
    
      if($method == 'file') {
        $fp = fopen($logFileName,'ab');
            fwrite($fp, $entry);
            fclose($fp);
      } elseif($method == 'echo'){
          echo nl2br($entry);//browser
          flush();
      }
    
      return;
    }
    
    function getMicroTime(){
      list($usec, $sec) = explode(" ",microtime());
      return ((float)$usec + (float)$sec);
    }
    
    ?>
    So yer, I'm still testing on the format for "$destRdir = '/public_html/backup/';" atm as I dont think /public_html/backup/ is working, but I will leave it for a bit to see if it just takes time to make the backups.

    Has anyone got this working yet?
     
  6. gfxpixeldesigns

    gfxpixeldesigns Registered

    Joined:
    Jul 14, 2011
    Messages:
    3
    Likes Received:
    0
    Trophy Points:
    1
    Just curious did anyone figure this out ?
     
Loading...

Share This Page