Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use itertools::Itertools;
- use log::{debug, error, info, trace, warn, log_enabled};
- use std::collections::HashMap;
- use std::ffi::OsStr;
- use std::fs::File;
- use std::io::Write;
- use std::path::Path;
- use std::process::{Command, Output};
- use whoami::username;
- ///////////////////////////////////////////////////////////////////////
- //
- /*
- my $VERBOSE = q{-v};
- # mount->cmd needs T_FSTYPE and T_UUID
- $cmds->{'mount'}->{'cmd'} = $cmds->{'mount'}->{'bin'} . qq{ $VERBOSE -t $T_FSTYPE -U $T_UUID $FS_MOUNTPOINT } . $cmds->{'mount'}->{'opt'};
- # rsync-opt needs excludes filename, derived from T_UUID
- my $CHKSUM = q{};
- if ($RSYNC_CHECKSUMS) {
- INFO(q{Checksums for rsync are enabled});
- $CHKSUM = q{-c}
- };
- $cmds->{'rsync'}->{'opt'} = qq{-a $VERBOSE $CHKSUM --delete --delete-excluded --delete-before }
- . qq{--exclude-from=$backup_vols->{$T_UUID}->{'EXCLUDES'} };
- $cmds->{'rsync'}->{'cmd'} = qq{$cmds->{'ionice'}->{'bin'} $cmds->{'ionice'}->{'opt'} }
- . qq{$cmds->{'rsync'}->{'bin'} $cmds->{'rsync'}->{'opt'} }
- . qq{$backup_vols->{$T_UUID}->{'SOURCES'} $FS_MOUNTPOINT};
- */
- //
- //
- /*
- $cmds->{'rsync'}->{'cmd'} = qq{$cmds->{'ionice'}->{'bin'} $cmds->{'ionice'}->{'opt'} }
- . qq{$cmds->{'rsync'}->{'bin'}
- . qq{-a $VERBOSE $CHKSUM --delete --delete-excluded --delete-before }
- . qq{--exclude-from=$backup_vols->{$T_UUID}->{'EXCLUDES'} };
- . qq{$backup_vols->{$T_UUID}->{'SOURCES'} $FS_MOUNTPOINT};
- 'SOURCES' => '/boot /etc /home /opt /root /srv /storage /usr /var'
- */
- ///////////////////////////////////////////////////////////////////////
- fn test_rsync() {
- info!("test_rsync() - Begin.");
- info!("testing rsync with rpm exclusion file...");
- let mut command = Command::new("/usr/bin/ionice");
- command.arg("-c"); // scheduling class
- command.arg("3"); // idle
- command.arg("/usr/bin/rsync");
- command.arg("--dry-run");
- command.arg("-a"); // archive mode
- command.arg("-v"); // verbose
- // command.arg(""); // checksum
- command.arg("--delete");
- command.arg("--delete-excluded");
- command.arg("--delete-before");
- // command.arg("--exclude-from=rsync-excludes.txt"); // RPM EXCLUDES
- command.arg("--exclude-from=excludes-1tb.conf"); // VOLUME EXCLUDES
- command.arg("/boot"); // SOURCES
- command.arg("/etc"); // SOURCES
- command.arg("/home"); // SOURCES
- command.arg("/opt"); // SOURCES
- command.arg("/root"); // SOURCES
- command.arg("/srv"); // SOURCES
- command.arg("/storage"); // SOURCES
- command.arg("/usr"); // SOURCES
- command.arg("/var"); // SOURCES
- command.arg("/storage/tmp/rsync-test"); // FS_MOUNTPOINT
- let args: Vec<&OsStr> = command.get_args().collect();
- info!("Arguments to ionice: {:?}", args);
- match command.output() {
- Ok(o) => {
- // stdout
- match String::from_utf8(o.stdout) {
- Ok(stdout) => {
- for line in stdout.lines() {
- info!("stdout: {}", line);
- } // for
- }, // Ok(stdout)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match stdout
- // stderr
- match String::from_utf8(o.stderr) {
- Ok(stderr) => {
- for line in stderr.lines() {
- info!("stderr: {}", line);
- } // for
- }, // Ok(stderr)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match stderr
- }, // Ok(o)
- Err(e) => {
- error!("Could not run the command. Bailing out! {:?}", e);
- panic!("Could not run the command. Bailing out! {:?}", e);
- }, // Err
- } // match
- info!("test_rsync() - End.");
- } // fn test_rsync
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn main() {
- match setup_logger() {
- Ok(_) => info!("Logging initialized. (log level: {})", log::max_level()),
- Err(e) => {
- println!("Could not initialize logging: {e:?}. Bailing out! ");
- std::process::exit(1);
- },
- } // match setup_logger
- let username = username();
- info!("Running as user '{}'", username);
- if username.ne(&String::from("root")) {
- error!("YOU ARE NOT RUNNING AS 'root'! YOU WILL NOT GET A PROPER BACKUP!");
- }
- debug!("create_rsync_exclude_rpm_files()");
- create_rsync_exclude_rpm_files();
- info!("testing rsync w/ exclude file (--dry-run)");
- test_rsync();
- } // main
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn setup_logger() -> Result<(), fern::InitError> {
- fern::Dispatch::new()
- .format(|out, message, record| {
- out.finish(format_args!(
- "{} [{}] [{}] {}",
- chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
- record.target(),
- record.level(),
- message
- ))
- })
- .level(log::LevelFilter::Debug)
- .chain(std::io::stdout())
- .chain(fern::log_file("output.log")?)
- .apply()?;
- Ok(())
- } //setup_logger
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn get_all_rpm_files(f: &mut HashMap<String, i32>) {
- info!("Collecting exclusion list of files from all installed rpm packages...");
- let mut command = Command::new("/usr/bin/rpm");
- command.arg("-qal");
- match command.output() {
- Ok(output) => {
- process_rpm_file(f, output);
- },
- Err(e) => {
- error!("Could not run the command. Bailing out! {:?}", e);
- panic!("Could not run the command. Bailing out! {:?}", e);
- },
- } // match command.output()
- info!("HashMap has {} elements.", f.len());
- } // get_all_rpm_files
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn process_rpm_file(f: &mut HashMap<String, i32>, o: Output) {
- // stdout
- match String::from_utf8(o.stdout) {
- Ok(stdout) => {
- for line in stdout.lines() {
- trace!("{}", line);
- if Path::new(line).is_file() {
- trace!("{} is a regular file", line);
- // insert file, with some arbitrary value
- f.insert( line.to_string(), 1 ) ;
- } // if path exists
- else {
- debug!("{} is not a regular file. Skipped.", line);
- } // else
- } // for
- }, // Ok(stdout)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match
- // stderr
- match String::from_utf8(o.stderr) {
- Ok(stderr) => {
- for line in stderr.lines() {
- info!("stderr: {}", line);
- } // for
- }, // Ok(stderr)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match stderr
- } // fn process_rom_file
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn get_rpm_verify_info(f: &mut HashMap<String, i32>) {
- info!("Verifying files on exclusion list...");
- let mut command = Command::new("/usr/bin/ionice");
- command.arg("-c"); // scheduling class
- command.arg("3"); // idle
- command.arg("/usr/bin/rpm");
- command.arg("-Va"); // Verify all
- match command.output() {
- Ok(output) => {
- process_verify_entry(f, output);
- },
- Err(e) => {
- error!("Could not run the command. Bailing out! {:?}", e);
- panic!("Could not run the command. Bailing out! {:?}", e);
- },
- } // match command.output()
- info!("HashMap has {} elements.", f.len());
- } // get_rpm_verify_info
- ///////////////////////////////////////////////////////////////////////
- //
- //
- //
- ///////////////////////////////////////////////////////////////////////
- fn process_verify_entry(f: &mut HashMap<String, i32>, o: Output) {
- // stdout
- match String::from_utf8(o.stdout) {
- Ok(stdout) => {
- let mut file_list: Vec<&str> = Vec::new();
- for line in stdout.lines() {
- trace!("{}", line);
- if line.contains("(Permission denied)") {
- error!("{}", line);
- } // if line contains...
- else {
- let mut t: Vec<&str> = line.split_whitespace().collect();
- t.reverse();
- let _flags = t.pop().unwrap();
- t.reverse();
- let name = t.pop().unwrap();
- if Path::new(name).is_file() {
- file_list.push(name);
- }
- else {
- debug!("{} is a directory",name);
- }
- } // else line contains.
- } // for
- file_list.sort();
- file_list.dedup();
- info!("Removing changed files from exclusion list...");
- let mut removed_count = 0;
- for elem in file_list.iter() {
- f.remove(&elem.to_string());
- debug!("removed {} from HashMap", elem);
- removed_count += 1;
- trace!("HashMap has {} elements.", f.len());
- } // for...
- info!("Total removed from HashMap: {}", removed_count);
- }, // Ok(stdout)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match
- // stderr
- match String::from_utf8(o.stderr) {
- Ok(stderr) => {
- for line in stderr.lines() {
- info!("stderr: {}", line);
- } // for
- }, // Ok(stderr)
- Err(e) => {
- error!("Could not convert from UTF8. Bailing out! {:?}", e);
- panic!("Could not convert from UTF8. Bailing out! {:?}", e);
- }, // Err
- } //match stderr
- } // fn process_verify_entry
- ///////////////////////////////////////////////////////////////////////
- //
- // fn create_rsync_exclude_rpm_files()
- //
- // Write HashMap keys to rsync-format exclude file
- //
- ///////////////////////////////////////////////////////////////////////
- fn create_rsync_exclude_rpm_files() {
- info!("Creating rsync exclude file for unchanged rpm managed files...");
- let mut files: HashMap<String, i32> = HashMap::new();
- info!("HashMap has {} elements.", files.len());
- // step 1
- get_all_rpm_files(&mut files);
- trace!("HashMap has {} elements after get_all_rpm_files.", files.len());
- if log_enabled!(log::Level::Trace) {
- trace!("Raw {:?}", files);
- trace!("Contents of HashMap");
- for (file, status) in &files {
- trace!("[all-files-tag] {}: {}", file, status);
- }
- } // if log enabled
- // step 2
- get_rpm_verify_info(&mut files);
- trace!("HashMap has {} elements after get_rpm_verify_info.", files.len());
- if log_enabled!(log::Level::Trace) {
- trace!("Raw {:?}", files);
- trace!("Contents of HashMap");
- for (file, status) in &files {
- trace!("[all-rpm-tag] {}: {}", file, status);
- }
- } // if log enabled
- // step 3
- let mut exclude_file = File::create("rsync-excludes.txt").expect("Unable to create file");
- for file in files.keys().sorted() {
- let line = format!("{}\n", file);
- trace!("{}", line);
- exclude_file.write_all(line.as_bytes()).expect("Unable to write data");
- } // for...
- } // fn create_rsync_exclude_rpm_files()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement