From 5c3140a74f23935d43b4921a17af07246cbc9b37 Mon Sep 17 00:00:00 2001 From: Bert Burgemeister Date: Sun, 24 Jan 2010 03:02:09 +0100 Subject: [PATCH] Minor changes to documentation. --- doc/download.muse | 2 +- doc/footer.muse | 2 +- doc/index.muse | 2 +- doc/installation.muse | 6 +- doc/license.muse | 3 +- doc/sidebar.muse | 3 + doc/usage.muse | 2 +- fsck-pokinom | 8 +- html/robots.txt | 2 + monikop | 9 +- pokinom | 248 +++++++++++++++++++++++++++++--------------------- 11 files changed, 168 insertions(+), 119 deletions(-) create mode 100644 html/robots.txt diff --git a/doc/download.muse b/doc/download.muse index 9a25e87..f7a3f2e 100644 --- a/doc/download.muse +++ b/doc/download.muse @@ -1,4 +1,4 @@ -#title Monikop and Pokinom +#title Monikop (and Pokinom) #subtitle rsync between unconnected hosts #author Bert Burgemeister diff --git a/doc/footer.muse b/doc/footer.muse index f02fee3..4059480 100644 --- a/doc/footer.muse +++ b/doc/footer.muse @@ -1,2 +1,2 @@ #disable-tables t -Copyright © 2010 | [[mailto:trebbu@googlemail.com?subject=MONIKOP ][Bert Burgemeister]] +© 2010 | [[mailto:trebbu@googlemail.com?subject=MONIKOP ][Bert Burgemeister]] diff --git a/doc/index.muse b/doc/index.muse index d9f4105..950ea3f 100644 --- a/doc/index.muse +++ b/doc/index.muse @@ -1,4 +1,4 @@ -#title Monikop and Pokinom +#title Monikop (and Pokinom) #subtitle rsync between unconnected hosts #author Bert Burgemeister diff --git a/doc/installation.muse b/doc/installation.muse index 855b3f3..55628ba 100644 --- a/doc/installation.muse +++ b/doc/installation.muse @@ -1,4 +1,4 @@ -#title Monikop and Pokinom +#title Monikop (and Pokinom) #subtitle rsync between unconnected hosts #author Bert Burgemeister @@ -394,9 +394,11 @@ pid file = /var/run/rsyncd.pid correspond to settings =$rsync_passwd= and =$rsync_username= in [[installation#pokinom.config][pokinom.config]]: -m-operator:seCreT +m-operator:sEcReT +=/etc/rsyncd.secrets= must not be world-readable. + In =/etc/default/rsync=, change the line diff --git a/doc/license.muse b/doc/license.muse index 906ab7e..25be297 100644 --- a/doc/license.muse +++ b/doc/license.muse @@ -1,9 +1,8 @@ -#title Monikop and Pokinom +#title Monikop (and Pokinom) #subtitle rsync between unconnected hosts #author Bert Burgemeister - * License diff --git a/doc/sidebar.muse b/doc/sidebar.muse index 2d549df..7e7f0b1 100644 --- a/doc/sidebar.muse +++ b/doc/sidebar.muse @@ -18,3 +18,6 @@ Developer">BerliOS Developer Logo + +; TODO screen shots +; TODO news diff --git a/doc/usage.muse b/doc/usage.muse index 2fea6e3..450dda2 100644 --- a/doc/usage.muse +++ b/doc/usage.muse @@ -1,4 +1,4 @@ -#title Monikop and Pokinom +#title Monikop (and Pokinom) #subtitle rsync between unconnected hosts #author Bert Burgemeister diff --git a/fsck-pokinom b/fsck-pokinom index 841ab86..da0c2e4 100755 --- a/fsck-pokinom +++ b/fsck-pokinom @@ -45,7 +45,13 @@ if (qx(whoami) eq "root\n") { } @mount_output; map { my $device = $devices{$_}; - qx(umount $device && fsck -fp $device); + open(PIPE, "umount $device && fsck -fp $device |"); + while ( defined( my $line = ) ) { + chomp($line); + print "$line\n"; + } + close PIPE; + } keys %devices; } else { print "$0: only root can run this.\n"; diff --git a/html/robots.txt b/html/robots.txt new file mode 100644 index 0000000..eb05362 --- /dev/null +++ b/html/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: diff --git a/monikop b/monikop index a1b48e0..67dff8b 100755 --- a/monikop +++ b/monikop @@ -436,7 +436,6 @@ $destinations_monitor_thread = async { unless ($debug == 1) { # Talk to the user. - $display_thread = async { $SIG{TERM} = sub { endwin(); # Leave a usable terminal. @@ -449,9 +448,9 @@ unless ($debug == 1) { noecho(); curs_set(0); my $window_left = newwin(LINES() -8, 29, 0, 0); - my $window_right = newwin(LINES() - 8, 50, 0, 29); - my $window_center = newwin(5, 79, LINES() - 8, 0); - my $window_bottom = newwin(3, 79, LINES() - 3, 0); + my $window_right = newwin(LINES() -8, 50, 0, 29); + my $window_center = newwin(5, 79, LINES() -8, 0); + my $window_bottom = newwin(3, 79, LINES() -3, 0); $window_bottom->keypad(1); $window_bottom->nodelay(1); start_color; @@ -560,7 +559,7 @@ unless ($debug == 1) { sleep 2; if (++ $redraw_window_count > 5) { $redraw_window_count = 0; - redrawwin(); + redrawwin(); } doupdate(); } diff --git a/pokinom b/pokinom index cdae9cf..d116af6 100755 --- a/pokinom +++ b/pokinom @@ -1,6 +1,7 @@ #! /usr/bin/perl use strict; use warnings; +use File::Basename; use File::Rsync; use Thread 'async'; use threads::shared; @@ -27,7 +28,7 @@ if ($ARGV[0]) { ######################################## # Settings ######################################## -# Possible mount points. Must be unique in their tails after rightmost /. +# Possible mount points. my @usable_mount_points; # Directory relative to a mount point where new data resides. @@ -152,17 +153,26 @@ sub act_on_keypress { $shut_down_when_done = $shut_down_when_done ? 0 : 1; } } +my %being_deleted_thread; +my %rsync_worker_thread; +my $display_thread; + $ENV{USER} = $rsync_username if ($rsync_username); $ENV{RSYNC_PASSWORD} = $rsync_password if ($rsync_password); -sub restore_terminal_and_die { - endwin(); # Leave a usable terminal. - die "Signal $_[0] caught"; -} -$SIG{TERM} = 'restore_terminal_and_die'; +$SIG{TERM} = sub { + $display_thread->kill('TERM')->join; + die "Caught signal $_[0]"; +}; # Preparations done; sleeves up! +# Make sure we have dirs to put our logs in: +map { + my ($filename, $directory) = fileparse $_; + qx(mkdir -p $directory); +} ( $rsync_log_prefix, $interrupted_prefix ); + # Find usable (i.e. mounted) sources my @raw_mount_points = grep (s/\S+ on (.*) type .*/$1/, qx/mount/); chomp @raw_mount_points; @@ -182,8 +192,7 @@ map { $source_roots{make_key_from_path $_} = $_ } @sources; -my %being_deleted_thread; -# Clean up sources if necessary +# Clean up sources if necessary: map { my $p_i_d = $source_roots{$_} . '/' . $path_under_mount_point; my $p_i_d_being_deleted = @@ -192,12 +201,19 @@ map { async { qx(rm -rf $p_i_d_being_deleted 2> /dev/null); }; } keys %source_roots; -# This could be more sophisticated: +# Wait for $destination if necessary: +my $rsync_ping = File::Rsync->new; +my $empty_directory = dirname($rsync_log_prefix) . "/empty_directory"; +qx(rm -rf $empty_directory; mkdir -p $empty_directory); + +while (1) { + print "Waiting for $destination to become writable.\n"; + sleep 2; + $rsync_ping->exec({ src => $empty_directory, dest => $destination}); + last if $? == 0; +} -print "\nWaiting for $destination to become reachable.\n"; -sleep 10; -my %rsync_worker_thread; my %rsync_exec_form; # Set up and start things per source_root, in parallel: @@ -209,9 +225,12 @@ map { debug_print 'rsync_preparation_form:' . rsync_preparation_form ($_). "\n"; eval rsync_preparation_form $_; debug_print "EVAL RSYNC_PREPARATION_FORM $_: $@ \n"; - my $complete_source = $source_roots{$_} . '/' . $path_under_mount_point; - my $complete_source_backed_up = $source_roots{$_} . '/' . $path_under_mount_point_backed_up; - my @interrupted = qx((cd $complete_source 2> /dev/null && find ./ -path *$rsync_partial_dir_name/*)); + my $complete_source = + $source_roots{$_} . '/' . $path_under_mount_point; + my $complete_source_backed_up = + $source_roots{$_} . '/' . $path_under_mount_point_backed_up; + my @interrupted = + qx((cd $complete_source 2> /dev/null && find ./ -path *$rsync_partial_dir_name/*)); # Write exclusion list: don't transfer files Monikop gave up upon. grep s/\.(.*\/)$rsync_partial_dir_name\/(.*)/$1$2/, @interrupted; write_list $interrupted_prefix . $_, @interrupted; @@ -221,17 +240,21 @@ map { if (eval ($rsync_exec_form{$_}() )) { debug_print "EVAL RSYNC_EXEC_FORM (successful) $complete_source: $@ \n"; } else { - die "EVAL RSYNC_EXEC_FORM (failed) $complete_source: $@ \n"; + $display_thread->kill('TERM')->join if $display_thread; + # TODO: in case of overfull destination, warn nicer + warn "EVAL RSYNC_EXEC_FORM (failed) $complete_source: $@ \n"; + threads->exit(); } } $progress_ratios{$_} = "Wait"; $speeds{$_} = "-"; - } + }; } keys %source_roots; -# Repeat rsync runs, this time sequentially, in order to get the newest of a file -# which may exist in multiple versions on different sources: +# Repeat rsync runs, this time sequentially, in order to get the newest of a +# file which may exist in multiple versions on different sources: my $rsync_worker_thread = async { + sleep 4; map { $rsync_worker_thread{$_}->join; debug_print "JOINED $_\n"; @@ -242,9 +265,12 @@ my $rsync_worker_thread = async { my $rsync_log_name = $rsync_log_prefix . $_; eval rsync_preparation_form $_; debug_print "EVAL RSYNC_PREPARATION_FORM $_: $@ \n"; - my $complete_source = $source_roots{$_} . '/' . $path_under_mount_point; - my $complete_source_backed_up = $source_roots{$_} . '/' . $path_under_mount_point_backed_up; - my @interrupted = qx((cd $complete_source 2> /dev/null && find ./ -path *$rsync_partial_dir_name/*)); + my $complete_source = + $source_roots{$_} . '/' . $path_under_mount_point; + my $complete_source_backed_up = + $source_roots{$_} . '/' . $path_under_mount_point_backed_up; + my @interrupted = + qx((cd $complete_source 2> /dev/null && find ./ -path *$rsync_partial_dir_name/*)); # Write exclusion list: don't transfer files Monikop gave up upon. grep s/\.(.*\/)$rsync_partial_dir_name\/(.*)/$1$2/, @interrupted; write_list $interrupted_prefix . $_, @interrupted; @@ -253,7 +279,10 @@ my $rsync_worker_thread = async { debug_print "EVAL RSYNC_EXEC_FORM (successful) $complete_source: $@ \n"; qx(mv $complete_source $complete_source_backed_up); } else { - die "EVAL RSYNC_EXEC_FORM (failed) $complete_source: $@ \n"; + $display_thread->kill('TERM')->join if $display_thread; + # TODO: in case of overfull destination, warn nicer + warn "EVAL RSYNC_EXEC_FORM (failed) $complete_source: $@ \n"; + threads->exit(); } } $progress_ratios{$_} = "Done"; @@ -266,92 +295,101 @@ my $rsync_worker_thread = async { } keys %source_roots; }; -if ($debug == 1) { -# Let the workers toil. - sleep; -} else { -# Let the workers toil and talk to the user. - my $redraw_window_count = 0; - initscr(); - cbreak(); - noecho(); - curs_set(0); - my $window_top = newwin(LINES() - 8, 79, 0, 0); - my $window_center = newwin(5, 79, LINES() - 8, 0); - my $window_bottom = newwin(3, 79, LINES() - 3, 0); - $window_bottom->keypad(1); - $window_bottom->nodelay(1); - start_color; - init_pair 1, COLOR_MAGENTA, COLOR_BLACK; - init_pair 2, COLOR_RED, COLOR_BLACK; - init_pair 3, COLOR_CYAN, COLOR_BLACK; - init_pair 4, COLOR_YELLOW, COLOR_BLACK; - my $MAGENTA = COLOR_PAIR(1); - my $RED = COLOR_PAIR(2); - my $CYAN = COLOR_PAIR(3); - my $YELLOW = COLOR_PAIR(4); - while (1) { - $window_top->attron($CYAN); - $window_top->box(0,0); - $window_top->addstr(0, 30, " P r o g r e s s "); - $window_top->attroff($CYAN); - my $sources_format = "%-25s%-18s%-8s"; - $window_top->attron(A_BOLD); - $window_top->addstr(1, 12, - sprintf ($sources_format, - "Source Medium", "Speed", "To Do")); - $window_top->attroff(A_BOLD); - my $line_number = 2; - map { - my $source = $_; - $window_top->attron($CYAN); - $window_top->attron($RED) if $done{$source}; - $window_top->addstr($line_number, 12, - sprintf($sources_format, - substr($source_roots{$source}, 0, 24), - substr($speeds{$source}, 0, 17), - substr($progress_ratios{$source}, -8, 8))); - ++ $line_number; - $window_top->addstr($line_number, 1, - sprintf($sources_format, "", "", "", "")); - $window_top->attroff($RED); - $window_top->attroff($CYAN); - } sort (keys %source_roots); - $line_number = 0; - map { - $window_center->addstr($line_number, 2, $_); - ++ $line_number; - } @pokinom_banner; - $window_center->move(0, 0); - - $window_bottom->box(0,0); - $window_bottom->attron(A_BOLD); - $window_bottom->addstr(1, 3, - sprintf ("[F3]: Turn off now.%54s", - $shut_down_when_done ? "Turning off when done. [F9]: Stay on." - : "Staying on. [F9]: Turn off when done.")); - $window_bottom->attroff(A_BOLD); - - $window_top->noutrefresh(); - $window_bottom->noutrefresh(); - $window_center->noutrefresh(); # Last window gets the cursor. - sleep 2; - if (++ $redraw_window_count > 5) { - $redraw_window_count = 0; - clearok(1); - } - doupdate(); - act_on_keypress($window_bottom->getch()); - if (! grep(/0/, values %done) && $shut_down_when_done) { - qx ($shut_down_action); - } - } - endwin(); +unless ($debug == 1) { +# Talk to the user. + $display_thread = async { + $SIG{TERM} = sub { + endwin(); # Leave a usable terminal. + threads->exit() + }; + + my $redraw_window_count = 0; + initscr(); + cbreak(); + noecho(); + curs_set(0); + my $window_top = newwin(LINES() - 8, 79, 0, 0); + my $window_center = newwin(5, 79, LINES() - 8, 0); + my $window_bottom = newwin(3, 79, LINES() - 3, 0); + $window_bottom->keypad(1); + $window_bottom->nodelay(1); + start_color; + init_pair 1, COLOR_MAGENTA, COLOR_BLACK; + init_pair 2, COLOR_RED, COLOR_BLACK; + init_pair 3, COLOR_CYAN, COLOR_BLACK; + init_pair 4, COLOR_YELLOW, COLOR_BLACK; + my $MAGENTA = COLOR_PAIR(1); + my $RED = COLOR_PAIR(2); + my $CYAN = COLOR_PAIR(3); + my $YELLOW = COLOR_PAIR(4); + while (1) { + $window_top->attron($CYAN); + $window_top->box(0,0); + $window_top->addstr(0, 30, " P r o g r e s s "); + $window_top->attroff($CYAN); + my $sources_format = "%-25s%-18s%-8s"; + $window_top->attron(A_BOLD); + $window_top->addstr(1, 12, + sprintf ($sources_format, + "Source Medium", "Speed", "To Do")); + $window_top->attroff(A_BOLD); + my $line_number = 2; + map { + my $source = $_; + $window_top->attron($CYAN); + $window_top->attron($RED) if $done{$source}; + $window_top-> + addstr($line_number, 12, + sprintf($sources_format, + substr($source_roots{$source}, 0, 24), + substr($speeds{$source}, 0, 17), + substr($progress_ratios{$source}, -8, 8))); + ++ $line_number; + $window_top->addstr($line_number, 1, + sprintf($sources_format, "", "", "", "")); + $window_top->attroff($RED); + $window_top->attroff($CYAN); + } sort (keys %source_roots); + $line_number = 0; + map { + $window_center->addstr($line_number, 2, $_); + ++ $line_number; + } @pokinom_banner; + $window_center->move(0, 0); + + $window_bottom->box(0,0); + $window_bottom->attron(A_BOLD); + $window_bottom-> + addstr(1, 3, + sprintf ("[F3]: Turn off now.%54s", + $shut_down_when_done ? "Turning off when done. [F9]: Stay on." + : "Staying on. [F9]: Turn off when done.")); + $window_bottom->attroff(A_BOLD); + + $window_top->noutrefresh(); + $window_bottom->noutrefresh(); + $window_center->noutrefresh(); # Last window gets the cursor. + sleep 2; + if (++ $redraw_window_count > 5) { + $redraw_window_count = 0; + redrawwin(); + } + doupdate(); + act_on_keypress($window_bottom->getch()); + if (! grep(/0/, values %done) && $shut_down_when_done) { + qx ($shut_down_action); + } + } + endwin(); + }; } +sleep; + # Tidy up. (Except we don't reach this.) map { $being_deleted_thread{$_}->join if $being_deleted_thread{$_}; } keys %source_roots; -$rsync_worker_thread->join if $rsync_worker_thread{$_}; +$rsync_worker_thread->join if $rsync_worker_thread; +$display_thread->join if $display_thread; -- 2.11.4.GIT