#!/bin/bash # Script for updating the marvin program in the initrd. #set -e set -u # Variables - Default values # Local directory name containing the representation for the initrd ROBOT_LOCAL_DIR="./robot" # Remote directory in the initrd ROBOT_REMOTE_DIR="/robot" # Name of the script to launch the robot program ROBOT_START_SCRIPT="start.sh" # Build directory ROBOT_BUILD_DIR="." # Config directory ROBOT_CONF_DIR="$ROBOT_BUILD_DIR/rc" # Max size of the config directory (in bytes) ROBOT_MAX_SIZE="4000000" # Hostname of the robot ROBOT_HOST="pilipili" # In autonomous mode, wait time for bringing up the ssh deamon ROBOT_WAIT_TIME="2.5s" # Compression ROBOT_NOCOMPRESS=0 # Quiet ? ROBOT_QUIET=0 # SSH options ROBOT_SSH_OPTS="-o ConnectTimeout 1" # Force autonomous mode ROBOT_FORCE_AUTONOMOUS=0 if [ $# -gt 6 ] then usage fi while getopts "b:s:r:zaqh" option do case $option in b) ROBOT_BUILD_DIR="$OPTARG";; # d) ROBOT_LOCAL_DIR="$OPTARG";; s) ROBOT_CONF_MAX_SIZE="$OPTARG";; r) ROBOT_HOST="$OPTARG";; z) ROBOT_NOCOMPRESS=1;; a) ROBOT_FORCE_AUTONOMOUS=1;; q) ROBOT_QUIET=1;; h) help_initrd;; \?) help_initrd;; esac done # Log function # First parameter : "error message" # Seconde parameter : "level" log () { if (( $ROBOT_QUIET == 0 )); then log_prefix="[II]" log_line=1 if [ $# -eq 2 ]; then case $2 in 1) log_prefix="[II]";; 2) log_prefix=" >>>";; 3) log_line=0;; *) log_prefix="[II]";; esac fi if (( $log_line == 1 )); then echo -en "$log_prefix $1 : " else echo -e "$1" fi fi } # Log error function # First parameter : "error message" log_error () { log "Error" 3 echo -e "[EE] $1" >&2 } # Usage - Help usage () { echo "Usage: $0 [-b ] [-s ] [-r ] [-z]" echo " -b : build directory of marvin" echo " -s : size max of binaries and config (in bytes)" echo " -r : robot host" echo " -z : disable compression" echo " -z : force automous mode (for second update)" echo " -q : be quiet (expect for errors)" echo " -h : this message" exit } check_rsync () { if [[ "x$(whereis rsync | cut -d ':' -f 2)" == "x" ]] then log_error "Please install rsync" exit 1 fi } # Check the structure (directory robot and startup script) check_create_structure () { log "Checking directory structure" 1 # Check the local directory exist if [[ ! -d $ROBOT_LOCAL_DIR ]] then mkdir -p $ROBOT_LOCAL_DIR/lib fi # Check we have a start script if [[ ! -x $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT ]] then # Create a default one cat < $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT # Startup script launched when the PC104 boot. # It will be executde by other script. # IMPORTANT : the commande must begin with a "./" ! # Example : # ./test_ai -z EOF chmod +x $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT # Need to tune it by the user log_error "Please tune your $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT" # XXX vim it ? exit 2 else # A little bit of cleaning for file in $ROBOT_LOCAL_DIR/* do if [[ ! -d $file && $file != "$ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT" ]] then rm -f $file fi done fi log "Ok" 3 } # Check that there is a line in the startup script for launchin a program and # a binary existing check_install_binary () { log "Checking binary and libraries" 1 if [[ $(grep -c "^\\./" $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT) -eq 0 ]] then log_error "No command found in your $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT" exit 3 fi for line in "$(grep "^\\./" $ROBOT_LOCAL_DIR/$ROBOT_START_SCRIPT)" do bin="$(echo "$line" | cut -d ' ' -f 1)" if [[ ! -x $ROBOT_BUILD_DIR/$bin ]] then log_error "Binary not found : $bin" exit 4 else # Copy the binary to the local dir cp -p $ROBOT_BUILD_DIR/$bin $ROBOT_LOCAL_DIR/ # Remove useless symbol strip -p $ROBOT_LOCAL_DIR/$bin # Copy needed libraries for lib in $(ldd $ROBOT_BUILD_DIR/$bin | cut -d ' ' -f 3) do cp -p $lib $ROBOT_LOCAL_DIR/lib done # For the one that begins with a / for lib in $(ldd $ROBOT_BUILD_DIR/$bin | grep -E "^[[:space:]]*/" | cut -f 2 |cut -f 1 -d ' ') do cp -p $lib $ROBOT_LOCAL_DIR/lib done fi done log "Ok" 3 } # Install the configuration check_install_config () { log "Checking configuration ($ROBOT_CONF_DIR)" 1 if [ ! -d $ROBOT_CONF_DIR ] then log_error "Configuration directory not found ($ROBOT_CONF_DIR)" exit 5 fi # There is no way to know the files needed, so we rsync everything rsync -azLu --exclude=.svn $ROBOT_CONF_DIR $ROBOT_LOCAL_DIR/ log "Ok" 3 } check_size () { log "Checking size" 1 # First we check the size if [[ $(du -bs $ROBOT_LOCAL_DIR | cut -f 1) -gt $ROBOT_MAX_SIZE ]] then log_error "$ROBOT_LOCAL_DIR is too big (> $ROBOT_MAX_SIZE)" exit 6 fi log "Ok" 3 } upload_data () { log "Uploading data to $ROBOT_HOST" 1 log "" 3 log "Checking $ROBOT_HOST is up" 2 # Check if host exist and is up ping -c 1 -w 1 -q $ROBOT_HOST > /dev/null case $? in 0) # Robot is online ! log "Ok" 3 ;; 1) # Host exist but is offline log_error "$ROBOT_HOST is currently down" exit 6 ;; 2) # Host does not exist log_error "$ROBOT_HOST does not exist" exit 7 ;; *) # Unknown error... log_error "Ping failed, unknown error" exit 8 ;; esac ROBOT_AUTONOMOUS=0 # Are we in automous mode ? log "Autonomous mode" 2 if (( $ROBOT_FORCE_AUTONOMOUS == 1 )); then ROBOT_AUTONOMOUS=1 fi nc -w 1 $ROBOT_HOST 1234 > /dev/null 2>&1 if [[ $? -eq 0 ]] then log "Yes" 3 ROBOT_AUTONOMOUS=1 sleep $ROBOT_WAIT_TIME else log "No" 3 fi # Mount the initrd log "Mouting the initrd" 2 if (( $ROBOT_AUTONOMOUS == 1 )); then ssh "$ROBOT_SSH_OPTS" root@$ROBOT_HOST "\ gunzip -f -c /initrd/last > /dev/shm/initrd_cur && \ mount -o loop /dev/shm/initrd_cur /mnt/initrd" else # TODO not implemented yet log "Not implemented..." 3 fi log "Ok" 3 # Rsync data log "Rsyncing data" 2 rsync -au $ROBOT_LOCAL_DIR/ root@$ROBOT_HOST:/mnt/initrd/$ROBOT_REMOTE_DIR/ log "Ok" 3 # Démonter et recompresser l'initrd voir rotater tout # TODO Backup, rotation, et less cp ! if (( $ROBOT_AUTONOMOUS == 1 )); then if (( $ROBOT_NOCOMPRESS == 1 )); then log "Umounting the initrd and move it" 2 ssh "$ROBOT_SSH_OPTS" root@$ROBOT_HOST "\ umount /mnt/initrd && \ mount -oremount,rw / && \ mv /dev/shm/initrd_cur /initrd/initrd1.gz && \ rm -f /dev/shm/initrd_cur && \ sync && \ mount -oremount,ro / && \ kill -SIGTERM 1" else log "Umounting the initrd and compress it" 2 # XXX Remove /tmp/initrd_cur after compression ? ssh "$ROBOT_SSH_OPTS" root@$ROBOT_HOST "\ umount /mnt/initrd && \ mount -oremount,rw / && \ gzip -f -4 -c /dev/shm/initrd_cur > /initrd/initrd1.gz && \ rm -f /dev/shm/initrd_cur && \ sync && \ mount -oremount,ro / && \ kill -SIGTERM 1" fi else log "Umounting the initrd and move it" 2 # TODO log "Not implemented..." 3 fi log "Ok... Rebooting" 3 } check_rsync check_create_structure check_install_binary check_install_config check_size upload_data