简体   繁体   中英

bash script rsync itself from remote host - how to?

I have multiple remote sites which run a bash script, initiated by cron (running VERY frequently -- 10 minutes or less), in which one of it's jobs is to sync a "scripts" directory. The idea is for me to be able to edit the scripts in one location (a server in a data center) rather than having to log into each remote site and doing any edits manually. The question is, what are the best options for syncing the script that is currently running the sync? (I hope that's clear).

I would imagine syncing a script that is currently running would be very bad. Does the following look feasible if I run it as the last statement of my script? pros? cons? Other options??

if [ -e ${newScriptPath} ]; then
    mv ${newScriptPath} ${permanentPath}" | at "now + 1 minute"
fi

One problem I see is that it's possible that if I use "1 minute" (which is "at's" smallest increment), and the script ends, and cron initiates the next job before "at" replaces the script, it could try to replace it during the next run of the script....

Changing the script file during execution is indeed dangerous (see this previous answer ), but there's a trick that (at least with the versions of bash I've tested with) forces bash to read the entire script into memory, so if it changes during execution there won't be any effect. Just wrap the script in {} , and use an explicit exit ( inside the {} ) so if anything gets added to the end of the file it won't be executed:

#!/bin/bash
{
    # Actual script contents go here

    exit
}

Warning: as I said, this works on the versions of bash I have tested it with. I make no promises about other versions, or other shells. Test it with the shell(s) you'll be using before putting it into production use.

Also, is there any risk that any of the other scripts will be running during the sync process? If so, you either need to use this trick with all of them, or else find some general way to detect which scripts are in use and defer updates on them until later.

So I ended up using the "at" utility, but only if the file changed. I have a ".cur" and ".new" version of the script on the local machine. If the MD5 is the same on both, I do nothing. If they are different, I wait until after the main script completes, then force copy the ".new" to the ".cur" in a different script.

I create the same lock file (name) for the update_script so another instance of the first script won't run if I'm changing it..

part in main script....

file1=`script_cur.sh`
file2=`script_new.sh`

if [ "$file1" == "$file2" ] ; then
    echo "Files have the same content"

else
    echo "Files are different, scheduling update_script.sh at command"
    at -f update_script.sh now + 1 minute
fi

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM