Procedure di backup (risiede tutto sul server di sviluppo)

9 Novembre 2006

Questo utente si occupa di tutte le procedure di backup, sia delle applicazioni online che di quelle in locale, Repository compreso.
Intanto creo utente e gruppo backup.

Questi i suoi crontab:

backup
00 20 * * * /home/backup/make_backup.sh
00 5 * * * /home/backup/get_backup.sh
00 14 * * * /home/backup/get_backup.sh
00 21 * * * /home/backup/get_backup.sh

Ogni backup risiede in 3 posti fisicamente diversi:

  • sullo stesso server da cui è generato e su cui risiede l’applicazione
  • sul server madre online
  • sul mio server di backup interno

Ho due tipologie di backup diverse, in base al server su cui risiede il sito/applicazione:

  • server su cui non ho la shell
  • server su cui ho la shell (posso lanciare script in Perl)

Ogni sera alle 20 vengono generati i backup con make_backup.sh sui server su cui non ho accesso con shell (vedi Aruba & C.).
Sui server dove ho la shell invece utilizzo lo script in Perl backupdb.pl che fa un dump del database e lo sposta via FTP sul server madre online.

La procedura get_backup.sh alle 5 del mattino, alle 14 e alle 20 va a prendersi i vari backup sul server madre.

In realtà per i server su cui non ho shell le copie sono 2, manca quella sul server madre. Non mi interessa però perchè sono siti/app minori.


get_backup.sh – preleva i backup dai vari server

9 Novembre 2006

### Preleva Backup dal dominio1
wget –output-file=log_bck.txt -N -l1 –ftp-user=<user> –ftp-password=<password> –no-remove-listing ftp://ftp.dominio1.it/backup/*.gz
### Preleva Backup dal dominio2
wget –output-file=log_bck.txt -N -l1 –ftp-user=<user> –ftp-password=<password> –no-remove-listing ftp://ftp.dominio2.it/backup/*.gz
### Preleva Backup dal dominio3
wget –output-file=log_bck.txt -N -l1 –ftp-user=<user> –ftp-password=<password> –no-remove-listing ftp://ftp.dominio3.it/backup/*.gz


make_backup.sh – effettua chiamate via HTTP per creare i backup

9 Novembre 2006

make_backup.sh:

# Backup su dominio 1
wget –spider http://www.******.**/db-bck.php?dbname=Sql*****_*
wget –spider http://www.******.**/db-bck.php?dbname=Sql*****_*
wget –spider http://www.******.**/db-bck.php?dbname=Sql*****_*
# Backup su dominio 2
wget –spider http://www.******.**/db-bck.php?dbname=Sql*****_*
# Backup su dominio 3
wget –spider http://www.******.**/db-bck.php?dbname=Sql*****_*

db-bck.php risiede sui diversi domini (vedi sopra) genera un dump del database.
La procedura è molto spartana ma fa il suo dovere, naturalmente deve trattarsi di piccoli database altrimenti non funzia. Però per tanti piccoli domini dove i database sono si e no qualche Mb va benissimo…

db-bck.php:

#### Parametri di configurazione per Backup Database
// $dbname DEVE essere passato come parametro GET, altrimenti lo script esce
if( !isset($dbname) )
{
exit;
}
$username = “********”;
$password = “********”;
$hostname = “***.***.***.***”;

#### Tipo di salvataggio
// Le opzioni sono: file -> invio diretto file con handler
// file_backup -> scrive backup in $dir_backup
$dir_backup = “backup/”;
$target = “file_backup”;
#### FINE Parametri ######################################

if($target==”file”)
{
header(‘Content-Type: application/octetstream’);
header(‘Content-Disposition: filename=”backup.sql”‘);
$asfile=”download”;
}

$crlf=”\r\n”;

$link = mysql_connect($hostname, $username, $password);
$database = mysql_select_db($dbname);

$dump_buffer=”";

$tables = mysql_query(“show tables from $dbname”);
$num_tables = mysql_num_rows($tables);

if($num_tables == 0)
{
echo “# No Tables Found”;
exit;
}

$dump_buffer.= “# DatabaseBackup $crlf”;
$dump_buffer.= “# Backup made:$crlf”;
$dump_buffer.= “# “.date(“F j, Y, g:i a”).”$crlf”;
$dump_buffer.= “# Database: $dbname$crlf”;
$dump_buffer.= “# Backed up tables : $dbname $crlf”;

$i = 0;
while($i “;
$dump_buffer.= “# ——————————————————–$crlf”;
$dump_buffer.= “$crlf#$crlf”;
$dump_buffer.= “# Table structure for table ‘$table’$crlf”;
$dump_buffer.= “#$crlf$crlf”;
$db = $table;
$dump_buffer.= get_table_def($table, $crlf,$dbname).”;$crlf”;
$dump_buffer.= “$crlf#$crlf”;
$dump_buffer.= “# Dumping data for table ‘$table’$crlf”;
$dump_buffer.= “#$crlf$crlf”;
$tmp_buffer=”";
get_table_content($dbname, $table, 0, 0, ‘my_handler’, $dbname);
$dump_buffer.=$tmp_buffer;

$i++;
$dump_buffer.= “$crlf”;
}

if($target==”file_backup”)
{
$dump_buffer = gzencode($dump_buffer);
$fp = fopen( $dir_backup . $dbname . ‘_’ . date(“w”) . ‘.sql.gz’, ‘wb’);
fwrite($fp, $dump_buffer);
fclose($fp);
echo “OK”;
} else {
echo $dump_buffer;
}
exit;

function get_table_def($table, $crlf,$dbname)
{

$schema_create = “DROP TABLE IF EXISTS `$table`;$crlf”;
$db = $table;

$schema_create .= “CREATE TABLE `$table` ($crlf”;

$result = mysql_query(“SHOW FIELDS FROM ” .$dbname.”.”
. $table) or die();
while($row = mysql_fetch_array($result))
{
$schema_create .= ” `$row[Field]` $row[Type]“;

if(isset($row["Default"]) && (!empty($row["Default"]) || $row["Default"] == “0″))
$schema_create .= ” DEFAULT ‘$row[Default]‘”;
if($row["Null"] != “YES”)
$schema_create .= ” NOT NULL”;
if($row["Extra"] != “”)
$schema_create .= ” $row[Extra]“;
$schema_create .= “,$crlf”;
}
$schema_create = ereg_replace(“,”.$crlf.”$”, “”, $schema_create);
$result = mysql_query(“SHOW KEYS FROM ” .$dbname.”.” .
$table) or die();
while($row = mysql_fetch_array($result))
{
$kname=$row['Key_name'];
$comment=(isset($row['Comment'])) ? $row['Comment'] : ”;
$sub_part=(isset($row['Sub_part'])) ? $row['Sub_part'] : ”;

if(($kname != “PRIMARY”) && ($row['Non_unique'] == 0))
$kname=”UNIQUE|$kname”;

if($comment==”FULLTEXT”)
$kname=”FULLTEXT|$kname”;
if(!isset($index[$kname]))
$index[$kname] = array();

if ($sub_part>1)
$index[$kname][] = $row['Column_name'] . “(” . $sub_part . “)”;
else
$index[$kname][] = $row['Column_name'];
}

while(list($x, $columns) = @each($index))
{
$schema_create .= “,$crlf”;
if($x == “PRIMARY”)
$schema_create .= ” PRIMARY KEY (`”;
elseif (substr($x,0,6) == “UNIQUE”)
$schema_create .= ” UNIQUE ” .substr($x,7).” (`”;
elseif (substr($x,0,8) == “FULLTEXT”)
$schema_create .= ” FULLTEXT “.substr($x,9).” (`”;
else
$schema_create .= ” KEY $x (`”;

$schema_create .= implode($columns,”, “) . “`)”;
}

$schema_create .= “$crlf)”;
if(get_magic_quotes_gpc()) {
return (stripslashes($schema_create));
} else {
return ($schema_create);
}
}
function get_table_content($db, $table, $limit_from = 0, $limit_to = 0,$handler)
{
// Defines the offsets to use
if ($limit_from > 0) {
$limit_from–;
} else {
$limit_from = 0;
}
if ($limit_to > 0 && $limit_from >= 0) {
$add_query = ” LIMIT $limit_from, $limit_to”;
} else {
$add_query = ”;
}

get_table_content_fast($db, $table, $add_query,$handler);

}

function get_table_content_fast($db, $table, $add_query = ”,$handler)
{
$result = mysql_query(‘SELECT * FROM ‘ . $db . ‘.’ . $table . $add_query) or die();
if ($result != false) {

@set_time_limit(1200); // 20 Minutes

// Checks whether the field is an integer or not
for ($j = 0; $j < mysql_num_fields($result); $j++) {
$field_set[$j] = mysql_field_name($result, $j);
$type = mysql_field_type($result, $j);
if ($type == ‘tinyint’ || $type == ’smallint’ || $type == ‘mediumint’ || $type == ‘int’ ||
$type == ‘bigint’ ||$type == ‘timestamp’) {
$field_num[$j] = true;
} else {
$field_num[$j] = false;
}
} // end for

// Get the scheme
if (isset($GLOBALS['showcolumns'])) {
$fields = implode(‘, ‘, $field_set);
$schema_insert = “INSERT INTO `$table` ($fields) VALUES (“;
} else {
$schema_insert = “INSERT INTO `$table` VALUES (“;
}

$field_count = mysql_num_fields($result);

$search = array(“\x0a”,”\x0d”,”\x1a”); //\x08\\x09, not required
$replace = array(“\\n”,”\\r”,”\Z”);

while ($row = mysql_fetch_row($result)) {
for ($j = 0; $j < $field_count; $j++) {
if (!isset($row[$j])) {
$values[] = ‘NULL’;
} else if (!empty($row[$j])) {
// a number
if ($field_num[$j]) {
$values[] = $row[$j];
}
// a string
else {
$values[] = “‘” . str_replace($search, $replace, addslashes($row[$j])) . “‘”;
}
} else {
$values[] = “””;
} // end if
} // end for

$insert_line = $schema_insert . implode(‘,’, $values) . ‘)’;
unset($values);

// Call the handler
$handler($insert_line);
} // end while
} // end if ($result != false)

return true;
}

function my_handler($sql_insert)
{
global $crlf, $asfile;
global $tmp_buffer;

if(empty($asfile))
$tmp_buffer.= htmlspecialchars(“$sql_insert;$crlf”);
else
$tmp_buffer.= “$sql_insert;$crlf”;
}

function faqe_db_error()
{
return mysql_error();
}

function faqe_db_insert_id($result)
{
return mysql_insert_id($result);
}


backupdb.pl – effettua dump database (server con shell)

9 Novembre 2006

#!/usr/bin/perl

use strict;
use warnings; # replaces -w, but much better
use Net::FTP;

# Time vars per impostare ora del dump
my @timevars = localtime();

# Variabili per connessione FTP al server madre
my $server=”ftp.******”;
my $user=”*****”;
my $password=”*****”;
my $dir=”www.***.***/backup”;
my $db=”/home/**********/<dir_application>/tmp/<name_application>$timevars[6]_$timevars[2].sql.gz”;
my $success=”true”;
my $db_tran=”true”;

#This dumps the mysql tables for backup
`/usr/bin/mysqldump -u<user> -p<password> –opt <nome_db> | gzip > /home/**********/<dir_application>/tmp/<name_application>$timevars[6]_$timevars[2].sql.gz`;

my $ftp=Net::FTP->new($server) or $success=”false”;

$ftp->login($user, $password) or $success=”false”;
$ftp->pasv() or $success=”false”;
$ftp->binary() or $success=”false”;
$ftp->cwd($dir) or $success=’false’;
$ftp->put($db) or $db_tran=”false”;
$ftp->quit;

my $reason;
my $test=”true”;

if ($success eq “false”){$reason .=”Unsuccessful login\n\n”;
$test=”false”;}
if ($db_tran eq “false”){$reason .=”Unsuccessful file transfer db\n\n”;
$test=”false”;}

if ($test eq “false”) {
my $subject=”Backup on <nome_server> Failed !”;
my $to=’******@******.**’;

BEGIN {
$ENV{PATH}=”/bin:/usr/bin”;
delete @ENV{qw(IFS CDPATH ENV BASH_ENV) };
}
open MAIL,”| /usr/lib/sendmail -t -i -F’<dominio_server>‘ -f’HostingLinux\@<dominio_server>‘” or dienice(“Couldn’t open sendmail $!”);
print MAIL “To: $to\n”;
print MAIL “Reply-To: HostingLinux\@<dominio_server>\n”;
print MAIL “Subject: $subject\n\n”;
print MAIL $reason;
close MAIL or die(“Error closing sendmail: $!”);
}


Utente devel del server di sviluppo

9 Novembre 2006

Creato utente e gruppo devel.
Creata directory /home/devel/www dentro la quale sviluppo le applicazioni. Poi ho configurato Apache in modo da creare dei domini virtuali locali. Vedi file di configurazione httpd.conf
Per vederli da macchine Windorz devi configurare il file hosts aggiungendo righe del tipo:

127.0.0.1 localhost
192.168.1.3 gdm.luke.local

Per questo utente va poi configurato il CVS (Repository) e Samba per accedere direttamente ai file a Windorz.