| #!/bin/bash |
| # Copyright 2017 The Fuchsia Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| #### CATEGORY=Device management |
| ### reboot a target fuchsia system |
| |
| ## usage: fx reboot [-r|--recovery] [-b|--bootloader] |
| ## -r|--recovery Reboot into recovery image |
| ## -b|--bootloader Reboot into bootloader |
| ## |
| ## This will reboot the device specified with `fx set-device`; otherwise |
| ## one of the devices on the link-local network. |
| |
| set -e |
| |
| source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $? |
| fx-config-read |
| |
| function usage() { |
| fx-command-help |
| } |
| |
| reboot_type="reboot" |
| while [[ "$1" =~ ^- ]]; do |
| case "$1" in |
| -h|--help) |
| usage |
| exit 0 |
| ;; |
| -r|--recovery) |
| reboot_type="reboot-recovery" |
| ;; |
| -b|--bootloader) |
| reboot_type="reboot-bootloader" |
| ;; |
| *) |
| break |
| esac |
| shift |
| done |
| |
| if [[ $# -gt 1 ]]; then |
| usage |
| exit 1 |
| fi |
| |
| device="$(get-device-name)" || exit $? |
| |
| if [[ -z "$(get-fuchsia-device-addr)" ]]; then |
| echo >&2 "Could not find ${device} in Fuchsia, attempting to reboot using netboot (Zedboot)" |
| exec "${FUCHSIA_BUILD_DIR}/host-tools/netruncmd" "--nowait" "${device}" "dm ${reboot_type}" |
| fi |
| |
| echo "Rebooting ${device}..." |
| |
| # Check that the device is reachable over SSH, otherwise let the user know. |
| # This establishes a ControlMaster. |
| monotime=$(fx-command-run shell clock --monotonic) |
| if [[ $? -ne 0 ]]; then |
| fx-error "Could not reach ${device} over SSH" |
| exit 1 |
| fi |
| |
| # Note: the background and exit trick here loosely gives us a "successful" |
| # command completion, provided the shell parses our input. As dm reboot is |
| # synchronous, we can't wait for it to complete, as the shell/ssh get no |
| # shutdown message, and will simply observe a peer connection dropping. |
| # Sometimes the reboot races the exit, in which case this command also exits |
| # with error, but the following SSH check will fail (provided the device |
| # doesn't reboot to SSH in less than a few seconds), so the loop will exit with |
| # success. |
| fx-command-run shell "dm \"${reboot_type}\" & exit 0" |
| |
| # Wait for the SSH connection to go down. As we use ControlMaster, we can |
| # observe this using the control master check. |
| i=0 |
| while fx-command-run shell -O check > /dev/null 2>&1; do |
| if [[ "$monotime" -gt $(fx-command-run shell clock --monotonic) ]]; then |
| # If we get here, then we raced between reboot and check, the device |
| # rebooted so fast that someone reconnected our SSH ControlMaster before we |
| # observed it going down (this generally only happens if the 'exit 0' above |
| # also races, and `fx serve` is busy trying to re-connect). |
| exit 0 |
| fi |
| |
| sleep 0.5 |
| if [[ "$((i++))" -gt "10" ]]; then |
| fx-error "SSH still connected after $((i/2))s, reboot may have failed" |
| exit 1 |
| fi |
| done |