Выполнить программу в текущей оболочке в скрипте оболочки

Выполнить программу в текущей оболочке в скрипте оболочки

Я создал небольшой скрипт оболочки, который анализирует конфигурацию .ssh и позволяет мне выбрать запись с помощью fzf, а затем подключается к этому хосту:

#!/bin/bash

set -o nounset -o errexit -o pipefail

list_remote_hosts()
{
    choice="$(cat $HOME/.ssh/config | awk -v RS= -v FS=\\n -v IGNORECASE=1 '
        {
            ip = ""
            alias = ""
            id_file = ""
            username = ""
            port = ""

            for (j = 1; j <= NF; ++j) {
                split($j, tmp, " ")
                if (tmp[1] == "Host") { alias = tmp[2] }
                if (tmp[1] == "Hostname") { ip = tmp[2] }
                if (tmp[1] == "IdentityFile") { id_file = tmp[2] }
                if (tmp[1] == "User") { username = tmp[2] }
                if (tmp[1] == "Port") { port = tmp[2] }
            }

            if (ip || alias && alias != "*") {
                if (port == "")
                {
                    port = "22"
                }
                print "ssh " username "@" ip " -i " id_file " -p " port
            }
        }
    ' | fzf)"

    "$($choice)"
}

list_remote_hosts

Это работает, но у меня проблемы с передачей прав собственности на текущую оболочку. При подключении скрипт зависает (я полагаю, потому что ssh запускается в подоболочке). Как только я ввожу eg exit и команда ssh завершается, я вижу вывод.

Я хочу автоматически передать права собственности текущей оболочке при запуске скрипта, чтобы получить такое же поведение, как при запуске команды ssh из моего терминала.

Я пробовал всевозможные вещи, такие как добавление && zshили использование evalor exec, но ничего из этого не сработало. Как мне это сделать?

решение1

Попробуйте изменить "$($choice)"на simply $choice(без кавычек) — это должно развернуть вывод awk в слова и вызвать команду ssh из текущего процесса.


Похоже, это может быть проблемой.

if (ip || alias && alias != "*") {
    if (port == "") port = "22"
    print "ssh " username "@" ip " -i " id_file " -p " port
}

Что произойдет, если ipпусто, но aliasне пусто? Вы войдете в блок, но нигде не используете переменную-псевдоним. Возможно, вам захочется

if (!ip) { ip = alias }
if (ip && ip != "*") { ...

Это может работать как альтернативный способ структурирования функции. Непроверено:

remote_host_connect() {
    awk '...' $HOME/.ssh/config \
    | fzf \
    | sh </dev/tty >/dev/tty 2>&1
}

У меня это работает как отдельный скрипт:

#!/bin/bash
eval "$(
    awk -v RS= -F'[[:space:]]+' '{
        for (i=1; i<NF; i+=2)
            data[$i]=$(i+1)
        ip = (data["HostName"] ? data["HostName"] : data["Host"])
        if (ip && ip != "*")
            printf "ssh %s@%s %s %s\n",
                (data["User"] ? data["User"] : ENVIRON["LOGNAME"]),
                ip,
                (data["IdentityFile"] ? "-i " data["IdentityFile"] : ""),
                "-p " (data["Port"] ? data["Port"] : 22)
    }' ~/.ssh/config \
    | fzf
)"

Связанный контент