#!/bin/sh # the next line restarts using tclsh8.6 \ exec tclsh8.6 "$0" "$@" # We need version 8.6 of TCL to get file tempfile. # Newer machines all have 8.6 installed on them and #!/bin/tclsh would have been sufficient. # Becca and some other old machines aren't as nice. # tclsh on becca will bring up version 8.5. # We are looking for /usr/local/bin/tclsh8.6 on becca, but that won't work on the newer machines. # This program will build the given projects. # This calls cvs update then make to do the bulk of the work. # If multiple projects overlap, we will not repeat any work. # If two projects are on the same machine, # we only call cvs update once on that machine, # and we only rebuild the shared directory once. # When more than one machine is involved, # We build each machine in parallel. # Typically top_dir would be /home/phil/cpp_alert_server. # We will be moving around to different directories to build their contents. # And we will be logging into different machines, so we need an absolute path. set top_dir [file dirname [file dirname [file normalize [info script]]]] # Read the file names from the hosts directory for a particular server. # These are the machines that are currently running this server. proc get_hosts {admin_dir} { global top_dir glob -tails -directory $top_dir/admin/$admin_dir/hosts * } #puts "top_dir = $top_dir" # The user gives us the admin directory as an input. # And we use the admin directory to find the hosts associated with this server. # Source is where we go to build the server. set admin_to_source { alert_ms fast_alert_search micro_proxy micro_proxy misc_ms misc_ms oddsmaker oddsmaker toplist_ms fast_alert_search toplist_old fast_alert_search } # If you don't ask for any servers, we print instructions then exit. if {[llength $argv] == 0} { set message {Please list one or more servers on the command line:} dict for {admin source} $admin_to_source { append message \n $admin " (admin/" $admin "/hosts/*/source/" $source ")" } puts stderr $message exit 1 } cd $top_dir/admin #puts [pwd] # Call cvs update in these places. set cvs_dirs {} # Call make in these places. set to_make {} foreach admin_dir $argv { set source [dict get $admin_to_source $admin_dir] foreach host [get_hosts $admin_dir] { # Use the relative_location (like ax_alert_server/hosts/sinclair-2k) in the cvs command because cvs doesn't like absolute path names. # Use the final_location as a key to remove duplicate entries. set relative_location $admin_dir/hosts/$host set final_location [file readlink $relative_location] dict set cvs_dirs $final_location $relative_location/source dict set to_make $host $source 1 } } set cvs_dirs [dict values $cvs_dirs] #puts "cvs_dirs = $cvs_dirs" #puts "to_make = $to_make" exec >@ stdout 2>@ stdout cvs -q update {*}$cvs_dirs # Store the make commands in a file, then execute that file with tcsh. # That was the only good way I could find to execute all of the commands in parallel, but still exit this script when the last one finished. set script_handle [file tempfile script_name] puts $script_handle #!/bin/tcsh puts $script_handle {} dict for {host dirs} $to_make { set dirs [dict keys $dirs] set command {} append command "ssh $host " foreach dir $dirs { append command "cd $top_dir/source/$dir \\; make clean \\; " } foreach dir $dirs { append command "cd $top_dir/source/$dir \\; make \\; " } append command " ; echo $host DONE &" puts $script_handle $command } close $script_handle file attributes $script_name -permissions 0500 #puts $script_name set exec_handle [open "| $script_name 2>@ stderr" r] while {![eof $exec_handle]} { puts [gets $exec_handle] } file delete $script_name puts {ALL DONE}