update 2.58 KB
Newer Older
1
#!/usr/bin/perl -wT
2
use Getopt::Std;
3
4
5
6
7
use English;
use Fcntl ':flock';
use POSIX qw(strftime);

#
8
9
# Update the system with new accounts/mounts/etc. Use -i for immediate
# (no waiting if it cannot get the lock).
10
#
11
12
13
14
15
16
17
18
sub usage()
{
    print "Usage: update [-i]\n";
    exit(1);
}
my $optlist   = "i";
my $batchmode = 1;
my $immediate = 0;
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

#
# Untaint path
#
$ENV{'PATH'} = '/bin:/sbin:/usr/bin:/usr/local/bin:/usr/local/etc/testbed';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};

#
# Load the OS independent support library. It will load the OS dependent
# library and initialize itself. 
# 
use lib "/usr/local/etc/testbed";
use libsetup;

#
# Turn off line buffering on output
#
$| = 1;

#
# Must be setuid root.
# 
if ($EUID != 0) {
    die("*** $0:\n".
	"    Must be root! Maybe not installed properly?\n");
}

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#
# Parse command arguments. Once we return from getopts, all that should be
# left are the required arguments.
#
%options = ();
if (! getopts($optlist, \%options)) {
    usage();
}
if (defined($options{"i"})) {
    $batchmode = 0;
    $immediate = 1;
}
if (@ARGV) {
    usage();
}

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#
# If not invoked as real root, then must be invoked as emulabman.
#
if ($UID) {
    my ($pwname) = getpwuid($UID) or
	die("*** $0:\n".
	    "    $UID is not in the password file!\n");

    if ($pwname ne "emulabman") {
	die("*** $0:\n".
	    "    You do not have permission to run this script!\n");
    }

    #
    # But must run as real root!
    #
    $UID = 0;
}

#
# Local config.
#
my $lockfile  = "/var/tmp/node_update_lockfile";

#
# Reuse the same log file so we can track errors.
#
my $logname = "/tmp/account_update.debug";

#
# Put this into the background so that the ssh can return immediately.
# 
if ($batchmode && TBBackGround($logname)) {
    #
    # Parent exits normally
    #
    exit(0);
}

if ($batchmode) {
    my $date = POSIX::strftime("20%y/%m/%d %H:%M:%S", localtime());

    print "------------------------------------------------------------\n";
    print "$date\n";
    print "------------------------------------------------------------\n";
}

#
# We do not want multiple invocations of this script running concurrently!
# Use a lock file to serialze.
#
open(LOCK, ">>$lockfile") ||
    die("Could not open $lockfile\n");

my $count = 0;
while (flock(LOCK, LOCK_EX|LOCK_NB) == 0) {
118
119
120
121
122
    if ($immediate) {
	print "Another update in progress. Exiting ...\n";
	close(LOCK);
	exit(1);
    }
123
    print "Another update in progress. Waiting a moment ...\n";
124
125
   
    if ($count++ > 20) {
126
127
128
129
130
	die("Could not get the lock after a long time!\n");
    }
    sleep(5);
}

131
remotenodeupdate($batchmode);
132
133
134

close(LOCK);
exit(0);