|  | #!/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 | 
|  | ### start a remote interactive shell in the target device | 
|  |  | 
|  | ## usage: fx shell [-h|--help] [--check | [<ssh flags>] <command>] | 
|  | ## | 
|  | ## Creates an SSH connection with a device and executes a command. | 
|  | ## | 
|  | ## Arguments: | 
|  | ##   -h|--help    Print out this message. | 
|  | ##   --check      Diagnose SSH keys and show relevant information about SSH keys | 
|  | ##                and the target device and exit. | 
|  | ##   <ssh flags>  Flags and command are passed to SSH as is. Consult SSH help | 
|  | ##                for a list of available flags. | 
|  |  | 
|  | source "$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"/lib/vars.sh || exit $? | 
|  |  | 
|  | check=false | 
|  | case $1 in | 
|  | --check) | 
|  | check=true | 
|  | shift | 
|  | ;; | 
|  | -h|--help) | 
|  | fx-command-help | 
|  | exit 0 | 
|  | ;; | 
|  | esac | 
|  |  | 
|  | ${FUCHSIA_DIR}/tools/ssh-keys/gen-ssh-keys.sh || exit $? | 
|  |  | 
|  | if $check; then | 
|  | privkey="$(get-ssh-privkey)" | 
|  |  | 
|  | has_error=false | 
|  |  | 
|  | # private key doesn't exist, should not happen because of gen-ssh-keys.sh above | 
|  | if [[ ! -f "${privkey}" ]]; then | 
|  | fx-error "Unexpected error: Private key does not exist: ${privkey}" | 
|  | exit 1 | 
|  | fi | 
|  |  | 
|  | pubkey="$(ssh-keygen -y -f "${privkey}")" || exit $? | 
|  |  | 
|  | # ignore stderr in case the authkeys file doesn't exist, as we will attempt | 
|  | # to create it below. | 
|  | authkeys="$(get-ssh-authkeys 2>/dev/null)" | 
|  |  | 
|  | # auth key doesn't exist | 
|  | if [[ ! -f "${authkeys}" ]]; then | 
|  | has_error=true | 
|  | fx-warn "Authorized keys file does not exist, attempting to create it: ${authkeys}" | 
|  | echo "${pubkey}" > "${authkeys}" | 
|  | echo "ok, created ${authkeys}" | 
|  | fi | 
|  |  | 
|  | if ! grep -q "$pubkey" "$authkeys"; then | 
|  | has_error=true | 
|  | fx-warn "Authorized keys file does not contain your Fuchsia public key, attempting to fix: ${authkeys}" | 
|  | echo "${pubkey}" >> "${authkeys}" | 
|  | echo "ok, fixed ${authkeys}" | 
|  | fi | 
|  |  | 
|  | fx-config-read | 
|  |  | 
|  | conffile="${FUCHSIA_BUILD_DIR}/ssh-keys/ssh_config" | 
|  | if [[ ! -f "${conffile}" ]] || ! grep -q "IdentityFile\s*$privkey" "$conffile"; then | 
|  | has_error=true | 
|  | fx-warn "ssh_config file doesn't exist or does not contain the correct private key, attempting to fix: ${conffile}" | 
|  | fx build ssh-keys/ssh_config | 
|  | if [[ $? -ne 0 || ! -f "${conffile}" ]] || ! grep -q "IdentityFile\s*$privkey" "$conffile"; then | 
|  | fx-error "Unexpected error, cannot regenerate ssh_config: ${conffile}" | 
|  | exit 1 | 
|  | fi | 
|  | echo "ok, created ${conffile}" | 
|  | fi | 
|  |  | 
|  | # ignore stderr in case device-finder is not built yet | 
|  | deviceaddr="$(get-fuchsia-device-addr 2>/dev/null)" | 
|  | deviceport="$(get-device-ssh-port 2>/dev/null)" | 
|  | echo "Device address: ${deviceaddr:-"unknown"}" | 
|  | echo "Device SSH port: ${deviceport:-"default"}" | 
|  | echo "SSH config: ${conffile}" | 
|  | echo "SSH private key file: ${privkey}" | 
|  | echo "SSH authorized keys file: ${authkeys}" | 
|  | echo | 
|  |  | 
|  | if $has_error; then | 
|  | fx-warn "Some issues were found and fixed. Please look above for more information" | 
|  | else | 
|  | echo "SSH configuration is in good shape, no issues detected" | 
|  | fi | 
|  |  | 
|  | exit 0 | 
|  | fi | 
|  |  | 
|  | args=() | 
|  | device_port="$(get-device-ssh-port)" || exit $? | 
|  | if [[ -n "${device_port}" ]]; then | 
|  | args+=( "-p" "${device_port}" ) | 
|  | fi | 
|  | device_addr="$(get-fuchsia-device-addr)" || exit $? | 
|  | if [[ -z "${device_addr}" ]]; then | 
|  | fx-error "Cannot find a device." | 
|  | exit 1 | 
|  | fi | 
|  | args+=( "${device_addr}" ) | 
|  |  | 
|  | args+=( "$@" ) | 
|  | # Note: I know there are people who don't like the host-key message, but DO NOT | 
|  | # apply -q here, it silences error messages and makes network and configuration | 
|  | # failures much harder to diagnose when helping people. The control master will | 
|  | # mean you only get one per TCP socket, which is once per newly booted host. | 
|  | # It's not a huge burden compared to end user support. | 
|  | fx-command-exec ssh "${args[@]}" |