
Я написал скрипт для настройки буфера обмена на рабочем столе с моего телефона 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 …