Last active
November 12, 2025 14:39
-
-
Save jul/ef4cbc4f506caace73c3c38b91cb1ea2 to your computer and use it in GitHub Desktop.
a framework for comparing present scripts execution with past ouput
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Licence : fait tout ce que tu veux excepter dire que tu l'as Γ©crit ou repomper sans citer jul | |
| usage() { | |
| cat << NAN | |
| # $0 (freeze|thaw|prior_result) input | |
| Blogpost-documentation generated by using \`$0 usage \` as a way to | |
| try to have all in one place ;) | |
| Source here : [https://gist.github.com/jul/ef4cbc4f506caace73c3c38b91cb1ea2](https://gist.github.com/jul/ef4cbc4f506caace73c3c38b91cb1ea2) | |
| NAN | |
| cat <<'MAN' | |
| A utility for comparing present scripts execution with past output | |
| ## Action | |
| ### freeze input | |
| record the script given in input with ONE INSTRUCTION PER LINE to compare result for future use. | |
| Except when **_OUTPUT** is set, output will automatically redirected to *replay_${input}* | |
| ### thaw input | |
| replay the command in input (a frozen script output) and compare them with | |
| past result | |
| ### prior_result input | |
| show the past recorded value in the input file | |
| ## Quickstart | |
| The code comes with its own testing data that are dumped in *input* | |
| It is therefore possible to try the code with the following input : | |
| ``` | |
| $ PROD=1 ./mr_freeze.sh freeze input "badass" "b c" | |
| ``` | |
| to have the following output | |
| ``` | |
| βοΈ recording: uname -a #immutable | |
| βοΈ recording: [ -n "$PROD" ] && echo "ok" || echo "ko" # mutable according to env variable | |
| βοΈ recording: date # mutable | |
| βοΈ recording: slmdkfmlsfs # immutable | |
| βοΈ recording: du -sh #immutable (kof kof) | |
| βοΈ recording: ssh "$A" 'uname -a' | |
| β [input] recorded. Use [./mr_freeze.sh thaw "replay_input" "badass" "b c"] to replay | |
| ``` | |
| ofc, it works because I have a station called *badass* with an ssh server. | |
| and then check what happens when you thaw the file accordingly. | |
| ``` | |
| $ ./mr_freeze.sh thaw "replay_input" "badass" "b c" | |
| ``` | |
| You have the following result: | |
| ``` | |
| π uname -a #immutable | |
| π₯ [ -n "$PROD" ] && echo "ok" || echo "ko" # mutable according to env variable | |
| @@ -1 +1 @@ | |
| -ok | |
| +ko | |
| π₯ date # mutable | |
| @@ -1 +1 @@ | |
| -lun. 10 nov. 2025 20:21:14 CET | |
| +lun. 10 nov. 2025 20:21:17 CET | |
| π slmdkfmlsfs # immutable | |
| π du -sh #immutable (kof kof) | |
| π ssh "$A" 'uname -a' | |
| ``` | |
| Which means the commands replayed with same output except _date_ and the code checking for the env variable PROD and there is a diff of the output of the command. | |
| Since the script is using subtituable variables (\$3 ... \$10) being remapped to (\$A ... \$H) | |
| We can also change the target of the ssh command by doing : | |
| ``` | |
| $ PROD=1 ./mr_freeze.sh thaw "replay_input" "petiot" | |
| ``` | |
| which gives: | |
| ``` | |
| π uname -a #immutable | |
| π [ -n "$PROD" ] && echo "ok" || echo "ko" # mutable according to env variable | |
| π₯ date # mutable | |
| @@ -1 +1 @@ | |
| -lun. 10 nov. 2025 20:21:14 CET | |
| +lun. 10 nov. 2025 20:22:30 CET | |
| π slmdkfmlsfs # immutable | |
| π du -sh #immutable (kof kof) | |
| π₯ ssh "$A" 'uname -a' | |
| @@ -1 +1 @@ | |
| -Linux badass 6.8.0-85-generic #85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux | |
| +FreeBSD petiot 14.3-RELEASE-p5 FreeBSD 14.3-RELEASE-p5 GENERIC amd64 | |
| ``` | |
| It's also possible to change the output file by using _OUTPUT like this : | |
| ``` | |
| $ _OUTPUT=this ./mr_freeze.sh freeze input badass | |
| ``` | |
| which will acknowledge the passed argument : | |
| ``` | |
| β [input] created use [./mr_freeze.sh thaw "this" "badass"] to replay | |
| ``` | |
| And last to check what has been recorded : | |
| ``` | |
| $ ./mr_freeze.sh prior_result this | |
| ``` | |
| which gives : | |
| ``` | |
| π uname -a #immutable | |
| Linux badass 6.8.0-85-generic #85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux | |
| Status:0 | |
| -------------------------------------------------------------------------- | |
| π [ -n "$PROD" ] && echo "ok" || echo "ko" # mutable according to env variable | |
| ok | |
| Status:0 | |
| -------------------------------------------------------------------------- | |
| π date # mutable | |
| lun. 10 nov. 2025 20:21:14 CET | |
| Status:0 | |
| -------------------------------------------------------------------------- | |
| π slmdkfmlsfs # immutable | |
| ./mr_freeze.sh: ligne 165: slmdkfmlsfsΒ : commande introuvable | |
| Status:127 | |
| -------------------------------------------------------------------------- | |
| π du -sh #immutable (kof kof) | |
| 308K . | |
| Status:0 | |
| -------------------------------------------------------------------------- | |
| π ssh "$A" 'uname -a' | |
| Linux badass 6.8.0-85-generic #85-Ubuntu SMP PREEMPT_DYNAMIC Thu Sep 18 15:26:59 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux | |
| Status:0 | |
| -------------------------------------------------------------------------- | |
| ``` | |
| MAN | |
| if [ ! -z "$IS_SOURCE" ]; then | |
| return 1 | |
| else | |
| exit 1 | |
| fi | |
| } | |
| ### next funny projet testing functional bash | |
| map() { | |
| f=$1; | |
| shift | |
| while [ -n "$1" ]; do | |
| eval "$f" "$1" | |
| shift | |
| done | |
| } | |
| incr() { echo $(( $1 + 1 )); } | |
| if_true() { if [[ "$1" != "0" && "$1" != "" ]]; then echo "$1"; fi; } | |
| filter() { map if_true $@ ;} | |
| quote() { echo -n " \"$@\""; } | |
| #echo $( map incr 1 2 3 4 5 ) | |
| #echo $( filter 1 0 1 0 ) | |
| ### end of fun | |
| cat <<'DATA' > input | |
| uname -a #immutable | |
| [ -n "$PROD" ] && echo "ok" || echo "ko" # mutable according to env variable | |
| date # mutable | |
| slmdkfmlsfs # immutable | |
| du -sh #immutable (kof kof) | |
| ssh "$A" 'uname -a' | |
| DATA | |
| ACTION=${1:-freeze} | |
| INPUT=${2:-input} | |
| shift 2 | |
| ARG=() | |
| for v in A B C D E F G H; do | |
| eval export $v=\"$1\"; | |
| ARG+=("$1") | |
| shift | |
| done | |
| _exec() { | |
| eval "$@" 2>&1 | |
| return $? | |
| } | |
| n2bl() { tr "\n" '\f' ; } | |
| bl2n() { tr "\f" '\n' ; } | |
| HERE="# use $0 thaw replay_$INPUT to replay" | |
| freeze() { | |
| INPUT=${1} | |
| OUTPUT=${_OUTPUT:-replay_${1}} | |
| while IFS=$'\a' read -r LINE; do | |
| echo "βοΈ recording: $LINE" | |
| RES=$( _exec "$LINE" ) | |
| ST="$?" | |
| RES=$( echo $RES | n2bl ); | |
| HERE="$( echo -e "${HERE}\n$LINE\a$RES\a$ST\a$ST" )" | |
| done < "$INPUT" | |
| echo "$HERE" > $OUTPUT | |
| echo -n "β [${INPUT}] recorded. Use [$0 thaw \"$OUTPUT\" " | |
| echo -n $( map quote "${ARG[@]}") | |
| echo "] to replay" | |
| } | |
| prior_result() { | |
| INPUT=$1 | |
| cat $INPUT | tail -n +2 | while IFS=$'\a' read -ra LINE; do | |
| echo -e "π ${LINE[0]}" | |
| echo -n ${LINE[1]} | bl2n | |
| echo "Status:${LINE[2]}" | |
| echo "--------------------------------------------------------------------------" | |
| done | |
| } | |
| thaw() { | |
| INPUT=$1 | |
| cat $INPUT | tail -n +2 | while IFS=$'\a' read -ra LINE; do | |
| FROM=$( echo ${LINE[1]} | bl2n ) | |
| ACTUAL=$( _exec ${LINE[0]} ) | |
| if [[ "$( echo $FROM | cat - )" != "$( echo $ACTUAL | cat - )" ]]; then | |
| #if diff -q <( echo $FROM ) <( echo $ACTUAL ); then | |
| echo "π₯ ${LINE[0]} " | |
| diff -ur --color=always <( echo "$FROM" ) <( echo "$ACTUAL" ) | tail -n +3 | |
| else | |
| echo -e "π ${LINE[0]}" | |
| fi | |
| done | |
| } | |
| if [ "$0" = "$BASH_SOURCE" ]; then | |
| [ -z "$INPUT" ] && usage | |
| $ACTION $INPUT | |
| else | |
| IS_SOURCE=1 | |
| return 1 | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment