bashself-updating

Bash : How to create a Bash script that has the ability to update itself?


Goal : Create a bash script that can update itself

Example

./my-script.sh 
 $ Hello world

Then when supplied with argument to update itself

./my-script.sh --update

./my-script.sh
$ Hello World Updated!

Problem : Unable to update script while loaded in memory

Things I've tried

#!/bin/bash

function update {
 
 urlOfUpdatedVersion="..."
 existingScriptLocation = "..."
 myLocalPath="..."

 wget $urlOfUpdatedVersion > $myLocalPath/my-script.sh

 mv myLocalPath/my-script.sh $existingScriptLocation
}

if [[ "$1" == "--update" ]]; then
 update
fi

echo "Hello World"

For sake of simplicity assume the updated script that gets pull down from the 'wget' is the exact same but with the following echo update

echo "Hello World Updated"

Solution

  • Updating a script while its running can be hard because the script is already loaded in memory, so it can be difficult to modify it directly. But you can use a turnaround for this.

    Here is an example of how I would apply this :

    #!/bin/bash
    
    function update {
        urlOfUpdatedVersion="https://example.com/path/to/updated-script.sh"
        existingScriptLocation="$(realpath "$0")"
        tempScriptLocation="/tmp/my-script.sh"
    
        # Download the updated version to a temporary location
        wget -q -O "$tempScriptLocation" "$urlOfUpdatedVersion"
    
        # Replace the current script with the updated version
        if [[ -f "$tempScriptLocation" ]]; then
            mv "$tempScriptLocation" "$existingScriptLocation"
            chmod +x "$existingScriptLocation"
            echo "Script updated successfully."
    
            # Optionally, you can run the updated script
            exec "$existingScriptLocation"
        else
            echo "Failed to download the updated script."
            exit 1
        fi
    }
    
    if [[ "$1" == "--update" ]]; then
        update
        exit 0
    fi
    
    echo "Hello World"