команда ssh не завершается

команда ssh не завершается

Я написал скрипт для настройки буфера обмена на рабочем столе с моего телефона Android.

#!/bin/sh

ssh -Y user@host "export DISPLAY=:0; echo -n $(termux-clipboard-get) | xclip -selection clipboard"

Скрипт функционирует как и ожидалось, но не завершается. Мне приходится нажимать Ctrl+, Cчтобы вернуться к подсказке.

Я воспользовался этой -fопцией, и она немедленно возвращается. От man ssh:

-f
Запросы sshна переход в фоновый режим непосредственно перед выполнением команды. Это полезно, если sshбудет запрашиваться пароли или парольные фразы, но пользователь хочет, чтобы это было в фоновом режиме. […]

Я не уверен, что это правильный способ решения этой проблемы. Ему не нужно работать в фоновом режиме. Ему просто нужно выполнить команду и вернуться.

Почему мой не sshвозвращается? ssh -fХороший ли это способ? Есть ли лучший способ?

решение1

Отэтот ответ:

Выборки в X работают при взаимодействии двух X-клиентов: один X-клиент утверждает, что у него есть выборка (первичная, вторичная, буфер обмена), а другой X-клиент, который хочет вставить выборку, связывается с первым клиентом, чтобы получить ее.

В вашем случае оригинал xclipумирает, но его потомок выживает, чтобы заявить, что у него есть выбор, и обслуживать будущих клиентов, которые хотят вставить. Похоже, он не отсоединяется полностью, и сервер SSH ждет, пока он завершит работу; поэтому ваш sshклиент ждет, пока он завершит работу. Отсюда и необходимость в Ctrl+ C.

Позже, если другой клиент заявит, что у него есть выбор, то удаленный xclipвыйдет и разблокирует ваш локальный ssh. Это означает, что ваш обходной путь -fне так уж плох: фоновые процессы не будут накапливаться, будет максимум один остановленный ssh.

Связанный ответ пытается решить проблему, которая, на первый взгляд, несколько связана.Другой ответтам советует xsel. Действительно, в моих тестах это не блокирует:

ssh -Y user@host "export DISPLAY=:0; echo -n foobar | xsel -i -b"

Изменение xclipна xselимеет решающее значение. Тем не менее, ваша исходная команда может быть улучшена еще больше.

  • Я думаю, вам не нужно -Y(или -X), потому что удаленные команды не взаимодействуют с вашим локальным X-сервером. Достаточно установить DISPLAYправо, чтобы указать xselна нужный дисплей, которыйместныйк xsel.

  • Нет необходимости export. Переменная относится только к xsel, поэтому этого фрагмента должно быть достаточно:DISPLAY=:0 xsel -i -b

  • Серьёзный недостаток. $(termux-clipboard-get)расширяется локально, и все, что вы получите, termux-clipboard-getбудет встроено в строку, которую вы передаете удаленной оболочке дляинтерпретировалкак код.

    Например, если termux-clipboard-getвозвращается ; rm -f /very/important/file; true, то удаленная оболочка будет запущена

    export DISPLAY=:0; echo -n ; rm -f /very/important/file; true | …
    

    Видите, что он делает? Правильным решением будет передать ssh:

    termux-clipboard-get | ssh user@host 'DISPLAY=:0 xsel -i -b'
    

    Таким образом, вывод termux-clipboard-getникогда не будет рассматриваться как код.

  • Я полагаю, вы намеренно использовали echo -nвывод termux-clipboard-getбез какого-либо завершающего символа новой строки. Если это так, вам следует удалить завершающие символы новой строки локально ине полагаться наecho:

    printf '%s' "$(termux-clipboard-get)" | …
    

Окончательная форма может быть:

printf '%s' "$(termux-clipboard-get)" | ssh user@host 'DISPLAY=:0 xsel -i -b'

Обратите внимание, что команда удалит конечные символы новой строки даже из данных, которые должны интерпретироваться как двоичные и не изменяться. Символы NUL также будут проблематичными. Если вам нужно передать некоторые данные дословно, то просто передайте их termux-clipboard-getнапрямую:

termux-clipboard-get | ssh …

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