Removing leading
백업 작업을 실행하는 cron에서 "" 메시지를 제거하려고 합니다 tar
. 이메일에는 여전히 이러한 메시지가 있으며 저는 다음을 사용하고 있습니다.만성병 환자오류가 발생한 경우에만 이메일 보내기:
ERROR OUTPUT:
/bin/tar: Removing leading `/' from member names
/bin/tar: Removing leading `/' from hard link targets
/bin/tar: Removing leading `/' from member names
내가 얻은 옵션을 tar -czf
포함하도록 편집했습니다 .-C
이 스레드이와 같이.
my($tarcmd) = "$tar -czf $backupname -C / $args $backup";
앞서 언급한 슬래시를 어디서 제거할 수 있나요?Orville Bennett의 블로그 게시물?
아마도 스크립트의 이 부분 어딘가에 있지 않을까요?
# drobo=/path/to/drobo
if( /^\s*drobo\s*=\s*(.*)$/ ) {
$drobopath=$1;
}
# tarargs=global tar arguments
elsif( /^\s*tarargs\s*=\s*(.*)$/ ) {
$tarargs=$1;
}
# backup [condition] =/path/for/backup [tar args]
elsif( /^\s*backup\s*(\[[^\]]*\])?\s*=\s*(.*)$/ ) {
push(@backup,$2);
if( $1 ) {
$condition{$2} = $1;
전체 스크립트는 다음과 같습니다.
#!/usr/bin/perl -W
use POSIX;
# Global variables
# Host name will be used as name of directory for backups on drobo
my($hostname)=`/bin/hostname`;
chomp($hostname);
my($configfile)="/etc/drobo-backup.conf";
my($tar)="/bin/tar"; # Path to tar utility
my($mkdir)="/bin/mkdir"; # Path to mkdir utility
my($verbose)=0;
my($testmode)=0;
sub Usage {
print "Usage: drobo-backup [-v] [-c configfile]\n";
print " -v : verbose mode";
print " -c : specify configuration file (default $configfile)";
print " -n : printd but don't execute commands (for testing config)";
exit 1;
}
# Subroutine to back up one directory to drobo
sub do_backup {
my($drobo,$args,$backup,$cond) = @_;
# The backup arg may include per-backup tar args. Strip off these
# and quotes to get at the filename
my($backuppath)=$backup;
# If quoted, remove quotes for naming. Otherwise it is required not
# not to have embedded blanks so that per-backup tar arguments may follow.
if( $backuppath =~ /^"([^"]*)"/ ) { # double quotes
$backuppath = $1;
}
elsif( $backuppath =~ /^'([^']*)'/ ) { # single quotes
$backuppath = $1;
}
elsif( $backuppath =~ /^(\S*)/ ) { # otherwise no blanks in path
$backuppath = $1;
}
if( -d $backuppath || -f $backuppath ) { # check it is a valid dir or file
my($drobodir) = "$drobo/$hostname";
# make sure the drobo subdirectory for this host exists
my($mkdircmd) = "$mkdir $drobodir";
if( $verbose ) {
print "$mkdircmd\n";
}
if( ! ($testmode || -d $drobodir) ) {
system($mkdircmd);
}
# if it did not work, bail.
if( ! ($testmode || -d $drobodir) ) {
print "Failed to create destination dir $drobodir\n";
exit 1;
}
# construct tarfile name, e.g. usr-local.tgz
my($backupfilestem) = $backuppath;
# Sanitize the tarfile name
while($backupfilestem =~ s,^/,,) { next; } # remove any leading slash(es)
while($backupfilestem =~ s,/$,,) { next; } # remove any trailing slash(es)
$backupfilestem =~ s,/,-,g; # all internal slashes become hyphens
$backupfilestem =~ s/[^-\.\w]/X/g;# all remaining non-word chars exc . become X
my($backupname)="$drobodir/$backupfilestem-new.tgz";
my($backuprename) = "$drobodir/$backupfilestem.tgz";
my($tarcmd) = "$tar -czf $backupname -C / $args $backup";
if( $cond ) {
$cond =~ s/^\[//; # remove the [ ] around condition
$cond =~ s/\]$//;
$cond =~ s/BKPATH/$backuppath/g; # convenience substitutions
$cond =~ s/TARFILE/$backuprename/g;
$cond =~ s/TARDIR/$drobodir/g;
}
if( $cond && WEXITSTATUS(system("test $cond")) != 0 ) {
if( $verbose ) {
print "Condition [$cond] tests false\n";
print "No backup of $backuppath\n";
}
}
else {
if( $verbose ) {
if( $cond ) {
print "Condition [$cond] tests true\n";
}
print "$tarcmd\n";
}
# tar returns 0 for success, 1 for warnings such as file changed while
# being copied. So we take either as meaning success. Rename foo-new.tgz
# to the (usually existing) foo.tgz. N.B. system() returns status<<8.
if( !$testmode ) {
if( WEXITSTATUS(system($tarcmd)) >= 2 ) {
print "\nBackup of $backuppath FAILED\n\n";
# to avoid bad backup being renamed to good in second try, call it bad
$backuprename = "$drobodir/$backupfilestem-FAILED.tgz";
}
if( rename("$backupname","$backuprename") ) {
print "Backed up $backuppath to $backuprename\n";
}
else {
print "Failed to rename $backupname to $backuprename: $!\n";
}
}
}
}
else {
print "$backuppath is not a directory or file\n";
}
}
# default arguments to use on every backup
my($tarargs)="--atime-preserve --one-file-system";
# set default drobopath according to dsm (lc) or cis (rh) network
my($drobopath)="/path"; #
if($hostname =~ /\.our\.domain\.edu/) {
$drobopath="/path"; #
}
# Process command line arguments
while(@ARGV) {
if( $ARGV[0] eq "-c" ) { # -c configfile
shift (@ARGV);
if(@ARGV) {
$configfile = $ARGV[0];
}
else {
Usage();
}
}
elsif( $ARGV[0] eq "-v" ) { # -v (verbose mode)
++$verbose;
}
elsif( $ARGV[0] eq "-n" ) { # -n (no-exec mode)
$testmode = 1;
}
else { # unrecognized argument
Usage();
}
shift (@ARGV);
}
open(CONFIGFILE,$configfile) || die("Cannot open configfile $configfile: $!");
if($verbose) {
print "Reading configfile $configfile\n";
}
my(@backup);
my(%condition);
my($configline) = 0;
foreach (<CONFIGFILE>) {
$configline++;
if( /^\s*#/ || /^\s*$/ ) { # skip blank & comment lines (first nonblank is #)
next;
}
# drobo=/path/to/drobo
if( /^\s*drobo\s*=\s*(.*)$/ ) {
$drobopath=$1;
}
# tarargs=global tar arguments
elsif( /^\s*tarargs\s*=\s*(.*)$/ ) {
$tarargs=$1;
}
# backup [condition] =/path/for/backup [tar args]
elsif( /^\s*backup\s*(\[[^\]]*\])?\s*=\s*(.*)$/ ) {
push(@backup,$2);
if( $1 ) {
$condition{$2} = $1;
}
}
else {
print "Unknown config directive at line $configline in $configfile:\n";
print;
exit 1;
}
}
close(CONFIGFILE);
my($path);
foreach $path (@backup) {
do_backup($drobopath,$tarargs,$path,$condition{$path});
}
# For unknown reason, rename of some files often fails. Try again here.
foreach $tarfile ( glob("$drobopath/$hostname/*-new.tgz") ) {
$rename_name = $tarfile;
$rename_name =~ s/-new\.tgz$/.tgz/;
if( rename($tarfile,$rename_name) ) {
print "Second try renamed $tarfile to $rename_name\n";
}
}
답변1
Perl 스크립트에서는 .가 있는 파일에서 파일 이름을 foreach (<CONFIGFILE>)
읽고 push(@backup,$2);
. array( ) foreach $path (@backup)
의 각 항목 에 대해 do_backup()
파일 이름을 인수로 사용하여 서브루틴이 호출됩니다 $backup
. 지적하신 대로 이는 설정 시 변경되지 않습니다 $tarcmd
. 따라서 해결책은 다음 줄 앞에서 이 변수를 편집하는 것입니다.
$backup =~ s|/|| if $backup =~ m|^['"]?/|; # remove any leading slash
my($tarcmd) = "$tar -czf $backupname -C / $args $backup";
s|/||
변수가 패턴과 일치하는 경우 ^['"]?/
, 즉 시작 부분에 따옴표나 큰따옴표가 있을 수 있고 그 다음에는 슬래시가 있으면 첫 번째 슬래시는 ( ) 아무것도 없는 것으로 대체됩니다. 이는 이전 코드에서 이 변수에 지정된 경로가 공백을 보호하기 위해 따옴표로 묶일 수 있다고 가정했기 때문입니다.
그러나 -C /
경로가 슬래시로 시작하는 경우에만 이 작업을 수행하고 추가할 수 있으므로 확실하지 않은 경우에는 두 가지 버전이 있어야 합니다.
my($tarcmd);
if($backup =~ m|^['"]?/|){
$backup =~ s|/||; # remove any leading slash
$tarcmd = "$tar -czf $backupname -C / $args $backup";
}else{
$tarcmd = "$tar -czf $backupname $args $backup";
}
답변2
다음과 같은 작업을 수행해야 합니다.
tar -czf backup.tar.gz -C / $(ls /)
즉, 슬래시 없이 루트 디렉터리의 모든 파일과 디렉터리를 나열합니다. 그러나 루트 디렉터리에는 백업하고 싶지 않은 디렉터리 /proc
, 디렉터리 등과 같은 다양한 항목이 포함되어 있으므로 이는 그다지 현명한 방법이 아닐 수 있습니다 ./dev