diff --git a/src/Misc/layoutroot/run-helper.cmd.template b/src/Misc/layoutroot/run-helper.cmd.template new file mode 100644 index 00000000000..562038336dd --- /dev/null +++ b/src/Misc/layoutroot/run-helper.cmd.template @@ -0,0 +1,39 @@ +@echo off + +"%~dp0\bin\Runner.Listener.exe" run %* + +rem using `if %ERRORLEVEL% EQU N` insterad of `if ERRORLEVEL N` +rem `if ERRORLEVEL N` means: error level is N or MORE + +if %ERRORLEVEL% EQU 0 ( + echo "Runner listener exit with 0 return code, stop the service, no retry needed." + exit /b 0 +) + +if %ERRORLEVEL% EQU 1 ( + echo "Runner listener exit with terminated error, stop the service, no retry needed." + exit /b 0 +) + +if %ERRORLEVEL% EQU 2 ( + echo "Runner listener exit with retryable error, re-launch runner in 5 seconds." + ping 127.0.0.1 -n 6 -w 1000 >NUL + exit /b 1 +) + +if %ERRORLEVEL% EQU 3 ( + rem Sleep 5 seconds to wait for the runner update process finish + echo "Runner listener exit because of updating, re-launch runner in 5 seconds" + ping 127.0.0.1 -n 6 -w 1000 >NUL + exit /b 1 +) + +if %ERRORLEVEL% EQU 4 ( + rem Sleep 5 seconds to wait for the ephemeral runner update process finish + echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds" + ping 127.0.0.1 -n 6 -w 1000 >NUL + exit /b 1 +) + +echo "Exiting after unknown error code: %ERRORLEVEL%" +exit /b 0 \ No newline at end of file diff --git a/src/Misc/layoutroot/run-helper.sh.template b/src/Misc/layoutroot/run-helper.sh.template new file mode 100755 index 00000000000..ef54bd516b0 --- /dev/null +++ b/src/Misc/layoutroot/run-helper.sh.template @@ -0,0 +1,54 @@ +#!/bin/bash + +# Validate not sudo +user_id=`id -u` +if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then + echo "Must not run interactively with sudo" + exit 1 +fi + +# Run +shopt -s nocasematch + +safe_sleep() { + if [ ! -x "$(command -v sleep)" ]; then + if [ ! -x "$(command -v ping)" ]; then + COUNT="0" + while [[ $COUNT != 5000 ]]; do + echo "SLEEP" > /dev/null + COUNT=$[$COUNT+1] + done + else + ping -c 5 127.0.0.1 > /dev/null + fi + else + sleep 5 + fi +} + +bin/Runner.Listener run $* +returnCode=$? +if [[ $returnCode == 0 ]]; then + echo "Runner listener exit with 0 return code, stop the service, no retry needed." + exit 0 +elif [[ $returnCode == 1 ]]; then + echo "Runner listener exit with terminated error, stop the service, no retry needed." + exit 0 +elif [[ $returnCode == 2 ]]; then + echo "Runner listener exit with retryable error, re-launch runner in 5 seconds." + safe_sleep + exit 1 +elif [[ $returnCode == 3 ]]; then + # Sleep 5 seconds to wait for the runner update process finish + echo "Runner listener exit because of updating, re-launch runner in 5 seconds" + safe_sleep + exit 1 +elif [[ $returnCode == 4 ]]; then + # Sleep 5 seconds to wait for the ephemeral runner update process finish + echo "Runner listener exit because of updating, re-launch ephemeral runner in 5 seconds" + safe_sleep + exit 1 +else + echo "Exiting with unknown error code: ${returnCode}" + exit 0 +fi diff --git a/src/Misc/layoutroot/run.cmd b/src/Misc/layoutroot/run.cmd index df5fd390975..cd5cb68970d 100644 --- a/src/Misc/layoutroot/run.cmd +++ b/src/Misc/layoutroot/run.cmd @@ -13,21 +13,19 @@ if defined VERBOSE_ARG ( rem Unblock files in the root of the layout folder. E.g. .cmd files. powershell.exe -NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command "$VerbosePreference = %VERBOSE_ARG% ; Get-ChildItem -LiteralPath '%~dp0' | ForEach-Object { Write-Verbose ('Unblock: {0}' -f $_.FullName) ; $_ } | Unblock-File | Out-Null" -if /i "%~1" equ "localRun" ( - rem ******************************************************************************** - rem Local run. - rem ******************************************************************************** - "%~dp0bin\Runner.Listener.exe" %* -) else ( - rem ******************************************************************************** - rem Run. - rem ******************************************************************************** - "%~dp0bin\Runner.Listener.exe" run %* - rem Return code 4 means the run once runner received an update message. - rem Sleep 5 seconds to wait for the update process finish and run the runner again. - if ERRORLEVEL 4 ( - timeout /t 5 /nobreak > NUL - "%~dp0bin\Runner.Listener.exe" run %* - ) +rem ******************************************************************************** +rem Run. +rem ******************************************************************************** + +:launch_helper +copy run-helper.cmd.template run-helper.cmd /Y +call "%~dp0run-helper.cmd" %* + +if %ERRORLEVEL% EQU 1 ( + echo "Restarting runner..." + goto :launch_helper +) else ( + echo "Exiting runner..." + exit 0 ) diff --git a/src/Misc/layoutroot/run.sh b/src/Misc/layoutroot/run.sh index 03bb10adcf8..580ab934f29 100755 --- a/src/Misc/layoutroot/run.sh +++ b/src/Misc/layoutroot/run.sh @@ -1,64 +1,24 @@ #!/bin/bash -# Validate not sudo -user_id=`id -u` -if [ $user_id -eq 0 -a -z "$RUNNER_ALLOW_RUNASROOT" ]; then - echo "Must not run interactively with sudo" - exit 1 -fi - # Change directory to the script root directory # https://stackoverflow.com/questions/59895/getting-the-source-directory-of-a-bash-script-from-within SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -# Do not "cd $DIR". For localRun, the current directory is expected to be the repo location on disk. - -# Run -shopt -s nocasematch -if [[ "$1" == "localRun" ]]; then - "$DIR"/bin/Runner.Listener $* -else - "$DIR"/bin/Runner.Listener run $* - -# Return code 3 means the run once runner received an update message. -# Sleep 5 seconds to wait for the update process finish +cp -f run-helper.sh.template run-helper.sh +# run the helper process which keep the listener alive +while :; +do + "$DIR"/run-helper.sh $* returnCode=$? - if [[ $returnCode == 3 ]]; then - if [ ! -x "$(command -v sleep)" ]; then - if [ ! -x "$(command -v ping)" ]; then - COUNT="0" - while [[ $COUNT != 5000 ]]; do - echo "SLEEP" > /dev/null - COUNT=$[$COUNT+1] - done - else - ping -c 5 127.0.0.1 > /dev/null - fi - else - sleep 5 - fi - elif [[ $returnCode == 4 ]]; then - if [ ! -x "$(command -v sleep)" ]; then - if [ ! -x "$(command -v ping)" ]; then - COUNT="0" - while [[ $COUNT != 5000 ]]; do - echo "SLEEP" > /dev/null - COUNT=$[$COUNT+1] - done - else - ping -c 5 127.0.0.1 > /dev/null - fi - else - sleep 5 - fi - "$DIR"/bin/Runner.Listener run $* + if [[ $returnCode == 1 ]]; then + echo "Restarting runner..." else - exit $returnCode + echo "Exiting runner..." + exit 0 fi -fi +done diff --git a/src/Runner.Listener/Configuration/ConfigurationManager.cs b/src/Runner.Listener/Configuration/ConfigurationManager.cs index db6e84fee95..09de9ed1b4f 100644 --- a/src/Runner.Listener/Configuration/ConfigurationManager.cs +++ b/src/Runner.Listener/Configuration/ConfigurationManager.cs @@ -54,7 +54,7 @@ public RunnerSettings LoadSettings() Trace.Info(nameof(LoadSettings)); if (!IsConfigured()) { - throw new InvalidOperationException("Not configured. Run config.(sh/cmd) to configure the runner."); + throw new NonRetryableException("Not configured. Run config.(sh/cmd) to configure the runner."); } RunnerSettings settings = _store.GetSettings(); diff --git a/src/Runner.Listener/Runner.cs b/src/Runner.Listener/Runner.cs index 89dcbb94a35..aa14776bf29 100644 --- a/src/Runner.Listener/Runner.cs +++ b/src/Runner.Listener/Runner.cs @@ -408,7 +408,7 @@ private async Task RunAsync(RunnerSettings settings, bool runOnce = false) autoUpdateInProgress = true; var runnerUpdateMessage = JsonUtility.FromString(message.Body); var selfUpdater = HostContext.GetService(); - selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, !runOnce && HostContext.StartupType != StartupType.Service, HostContext.RunnerShutdownToken); + selfUpdateTask = selfUpdater.SelfUpdate(runnerUpdateMessage, jobDispatcher, false, HostContext.RunnerShutdownToken); Trace.Info("Refresh message received, kick-off selfupdate background process."); } else