garethgeorge / backrest

Backrest is a web UI and orchestrator for restic backup.
GNU General Public License v3.0
1.05k stars 34 forks source link

Hooks/Powershell: multi-line if-statements not executed #400

Open daniel-l opened 1 month ago

daniel-l commented 1 month ago

Describe the bug Hooks on windows installs with multi-line if-statements are not executing the multi-line part of the hook. If-statements have to be condensed into a one liner in order for that part of the hook to be executed as expected.

To Reproduce Example 1: hook not executing the if-statement:

$status = Invoke-RestMethod 192.168.0.102:5000/status/backup
echo $status.results
if (-not $status.results) { 
  Invoke-RestMethod 192.168.0.102:5000/wol/backup
  sleep 10 
} else {
  echo "online"
}

Hook output:

[script] [powershell -nologo -noprofile]
[script] $status = Invoke-RestMethod 192.168.0.102:5000/status/backup
[script] echo $status.results
[script] if (-not $status.results) { 
[script]   Invoke-RestMethod 192.168.0.102:5000/wol/backup
[script]   sleep 10 
[script] } else {
[script]   echo "online"
[script] }
[output] PS C:\Program Files\Backrest> $status = Invoke-RestMethod 192.168.0.102:5000/status/backup
[output] PS C:\Program Files\Backrest> echo $status.results
[output] True
[output] PS C:\Program Files\Backrest> if (-not $status.results) { 
[output] >>   Invoke-RestMethod 192.168.0.102:5000/wol/backup
[output] >>   sleep 10 
[output] >> } else {
[output] >>   echo "online"
[output] >> }>> 
task "run hook command hook plan/daniel_dokumente/hook/0" completed successfully

As you can see only the first 2 lines of the hook script are executed: saving the result of the webrequest into $status and echoing the variable. The following if-else-statement ist not executed.

Example 2: hook with a working "condensed" multi-line if-statement:

$status = Invoke-RestMethod 192.168.0.102:5000/status/backup
echo $status.results
if (-not $status.results) { Invoke-RestMethod 192.168.0.102:5000/wol/backup; sleep 10 } else { echo $status.results }

Hook output:

[script] [powershell -nologo -noprofile]
[script] $status = Invoke-RestMethod 192.168.0.102:5000/status/backup
[script] echo $status.results
[script] if (-not $status.results) { Invoke-RestMethod 192.168.0.102:5000/wol/backup; sleep 10 } else { echo $status.results }
[output] PS C:\Program Files\Backrest> $status = Invoke-RestMethod 192.168.0.102:5000/status/backup
[output] PS C:\Program Files\Backrest> echo $status.results
[output] True
[output] PS C:\Program Files\Backrest> if (-not $status.results) { Invoke-RestMethod 192.168.0.102:5000/wol/backup; sleep 10 } else { echo $status.results }
[output] results                                                
[output] -------                                                
[output] Packet successfully sent to backup:...
[output] 
[output] 
[output] PS C:\Program Files\Backrest> 
task "run hook command hook plan/daniel_dokumente/hook/0" completed successfully

Expected behavior I expect multi-line if-(else-)statements like in example 1 to be executed correctly. Unsure whether this is a bug or more of a feature request.

garethgeorge commented 1 month ago

A behavior I've noticed and need to patch is that powershell scripts seem to need a trailing new line, I'm curious if adding one fixes your first example?

daniel-l commented 1 month ago

I just tried the first example with an additional trailing new line - it does not work. I didn't expect it to work anyway as the script in example 2 has no trailing new line but is executed as planned. Trailing new lines do not seem to be missing here.

jonpas commented 2 weeks ago

I am experiencing this issue try to send a multine log output to Healthchecks.io via a hook.

The problem seems to be that the system finds the multiline command/string correctly (as we can see by >> markers), but does not know when to conclude them and just goes to the end, resulting in no execution of anything after the first multiline "break".

I have managed to work around it with the help of the above comments. Just add an empty newline at the bottom of multiline command (where it should end) AND an additional one overall. So if your script ends in a multiline command, add 2 newlines after it.

Example:

#!pwsh
curl -fsS -m 10 --retry 3 --data-raw '{{ .Summary }}' https://hc-ping.com/uuid/start

# empty line to terminate multiline output properly (backrest issue #400)