Как скопировать в буфер обмена OSX из удаленной оболочки с помощью iTerm2?

Используя iTerm2, я запускаю интерактивный сеанс SSH с удаленной машиной Linux (где pbcopyон недоступен). На удаленной машине с Linux я хотел бы захватить вывод какой-либо произвольной команды (например, ls *.foo) и волшебным образом появиться в моем буфере обмена OSX, чтобы, когда я нажимаю + v, он появлялся в любом приложении OSX, в которое я только что вставил. Это возможно? Я пробовал escape-коды, упомянутые на странице документации iTerm2 , и не могу заставить их работать.

@klanomath - спасибо, я подумаю об этом (я не уверен, что хочу настроить доступ к моей машине через ключи SSH, хотя, конечно, он может быть защищен паролем).
Для этого требуется X на удаленном сервере, которого там нет, и XQuartz, работающий на локальном сервере, из-за чего моя машина сильно нагревается. Но это может быть мой лучший выбор - спасибо!
затем комментарий nbren12 ко второму ответу ! ;-)
Я уже посмотрел на это - для этого по-прежнему требуются ключи SSH, и это единственный способ, которым я смогу это сделать, поскольку в одном случае использования я подключаюсь к удаленной машине по SSH из VPN-подключения, поэтому никаких статических IP или имя хоста. Другая проблема заключается в том, что у меня разные имена учетных записей пользователей на двух моих основных локальных компьютерах, но я могу решить это с помощью переменной среды или чего-то еще. Тем не менее, спасибо за усилия, я действительно ценю это.

Ответы (4)

Решение

Собрав воедино много информации из нескольких разных источников, вот что я придумал.

Локальный демон

На локальном компьютере (OSX) настройте демон для прослушивания определенного порта через launchd(см. ссылки ниже). Процесс-демон просто вызовет pbcopy, который возьмет все, что передано через via STDIN, и поместит его в буфер обмена. Для этого вам нужно настроить launchdфайл plist. Моя выглядела так:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>local.pbcopy.9999</string>
    <key>UserName</key>
    <string>joe</string>
    <key>Program</key>
    <string>/usr/bin/pbcopy</string>
    <key>StandardOutPath</key>
    <string>/tmp/pb9999.out</string>
    <key>StandardErrorPath</key>
    <string>/tmp/pb9999.err</string>
    <key>Sockets</key>
    <dict>
        <key>Listeners</key>
        <dict>
            <key>SockNodeName</key>
            <string>localhost</string>
            <key>SockServiceName</key>
            <string>9999</string>
        </dict>
    </dict>
    <key>inetdCompatibility</key>
    <dict>
        <key>Wait</key>
        <false/>
    </dict>
</dict>
</plist>

По соглашению имя файла plist должно быть именем метки с .plistдобавлением, поэтому для приведенного выше примера это будет local.pbcopy.9999.plist. Если вы хотите использовать порт, отличный от 9999, просто измените его везде (помните, что он должен быть выше 1024 и не должен быть хорошо известным портом, который вы, возможно, уже используете). Когда все заработает, вы можете удалить ключи StandardOutPathи StandardErrorPathи строки, так как они нужны только для отладки.

Чтобы загрузить демон, выполните следующую команду:

$ launchctl load local.pbcopy.9999.plist

Вы можете увидеть, что он загружен или удалить его с помощью следующих команд:

$ launchctl list local.pbcopy.9999
$ launchctl remove local.pbcopy.9999

Если вы хотите, чтобы это загружалось каждый раз, когда вы входите в систему, поместите файл plist в ~/Library/LaunchAgentsкаталог.

Примечание: вам нужно будет настроить это на каждом локальном хосте, на котором вы хотите, чтобы это работало.

Перенаправление портов SSH

Поскольку я мог получить доступ к удаленной машине с нескольких разных локальных компьютеров, я не могу жестко закодировать отправку данных с удаленной машины на конкретный хост. Чтобы сделать это максимально безболезненным и динамичным, я использовал переадресацию портов SSH для создания динамической ссылки с удаленного компьютера на локальный компьютер (как и почему это выходит за рамки этого ответа; см. ниже для получения дополнительной информации) . В частности, я создаю ссылку с порта 9997 удаленных машин на порт 9999 локального компьютера, который теперь слушает демон, благодаря вышеизложенному launchd. Я мог бы использовать порт 9999 как на удаленном, так и на локальном компьютере, но мне это не нужно.

Чтобы настроить этот туннель, выполните следующую команду:

$ ssh -R 9997:localhost:9999 user@remote.com

Вы можете удаленно подключаться к нескольким различным удаленным машинам с помощью одной и той же команды, и все они будут работать должным образом. Вы можете удаленно подключаться к одной и той же удаленной машине несколько раз с помощью одной и той же команды, и она будет работать, как и ожидалось; см. примечание ниже.

Если вам не хочется вводить -R 9997:localhost:9999при каждом вызове SSH, который вы делаете, вы можете поместить определение удаленной переадресации в файл конфигурации SSH, чтобы делать это автоматически. Вот пример из моего ~/.ssh/configфайла:

Host ufo*
  RemoteForward 9997 localhost:9999

При этом каждый раз, когда я подключаюсь по SSH к хосту, имя которого начинается с «ufo», автоматически устанавливается удаленная переадресация с 9997 на localhost:9999. Дополнительные параметры см. по ссылке на справочную страницу файла конфигурации ниже.

Отправка данных

На удаленном конце я использую netcatдля отправки желаемого контента обратно прослушивающему демону.

$ date | nc localhost 9997

Вы можете усложнять, как хотите:

$ nc localhost 9997 <<EOF
> `ls -ld *`
> `date`
> EOF

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

#!/bin/bash
cnt=`(netstat -lnptu 2>/dev/null) | grep 127.0.0.1:9999 | grep -v grep | wc -l`
if [[ $cnt -eq 1 ]]; then
    date | nc localhost 9999
fi

Наблюдения и предостережения

Вещи, которые я отметил:

  • pbcopyпрекрасно работает с Copy'em Paste
  • если вы инициируете более одного сеанса SSH с переадресацией одного и того же удаленного порта на один и тот же удаленный компьютер, только первый сеанс будет иметь какой-либо эффект; ни на одном конце не будет сообщено об ошибках типа «дубликат порта».
  • аналогично, если вы подключаетесь с нескольких разных локальных компьютеров к одному и тому же удаленному компьютеру, используя один и тот же удаленный порт (например, 9997), только первый будет иметь какой-либо эффект.

Справочные ссылки

Если у вас нет ncна удаленном хосте, это работает, по крайней мере, на RHEL:echo "howdy" > /dev/tcp/localhost/9997
Я использую это решение более 1 года, недавно заметил, что оно не поддерживает юникод. Например, буфер обмена был заполнен test‚ûú abcпосле echo "test➜ abc"|nc -w 0 localhost 9999, что означает преобразование ‚ûúв процессе, у кого-нибудь есть идеи по этому поводу?

удаленный pbcopy для iTerm2, похоже, является частью программного обеспечения, созданного специально для этой проблемы.

Если вы используете iTerm2 , есть более простой способ. Эта функция встроена в возможности интеграции оболочкиit2copy iTerm2 с помощью команды:

Usage: it2copy
          Copies to clipboard from standard input
       it2copy filename
          Copies to clipboard from file

Чтобы заставить его работать, выберите пункт меню iTerm2 -> Установить интеграцию с оболочкой при входе на удаленный хост, чтобы установить его в свою учетную запись. Как только это будет сделано, у вас будет доступ к it2copy, а также к множеству других команд с псевдонимами, которые обеспечивают классную функциональность.

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

Вы можете сделать это

ssh -ttt user@location "ksh -c 'ls *'" | pbcopy
Мне нужно решение для сеанса интерактивной оболочки — поясню выше.