¿Cómo copio al portapapeles OSX desde un shell remoto usando iTerm2?

Usando iTerm2, inicio una sesión SSH interactiva en una máquina Linux remota (donde pbcopyno está disponible). En la máquina Linux remota, me gustaría capturar la salida de algún comando arbitrario (por ejemplo, ls *.foo) y hacer que aparezca mágicamente en mi portapapeles OSX, de modo que cuando presione + vaparezca en cualquier aplicación OSX que acabo de pegar. es posible? Probé los códigos de escape mencionados en la página de documentos de iTerm2 y no puedo hacerlos funcionar.

@klanomath: gracias, lo consideraré (no estoy seguro de querer volver a configurar el acceso a mi máquina a través de claves SSH, aunque, por supuesto, podría estar protegido con contraseña).
Requiere X en el servidor remoto, que no está allí, y XQuartz ejecutándose en el servidor local, lo que hace que mi máquina se caliente. Pero podría ser mi mejor apuesta, ¡gracias!
¡entonces el comentario de nbren12 a la segunda respuesta ! ;-)
Ya lo miré: todavía requiere que se configuren las claves SSH, y es la única forma en que podría hacerlo, ya que un caso de uso me hace ingresar a la máquina remota desde una conexión VPN, por lo que no estático IP o nombre de host. Otro problema es que tengo diferentes nombres de cuenta de usuario en mis dos máquinas locales principales, pero podría resolverlo en una variable de entorno o algo así. Gracias por el esfuerzo, sin embargo, realmente lo aprecio.

Respuestas (4)

Solución

Reuniendo mucha información de varias fuentes diferentes, esto es lo que se me ocurrió.

Demonio local

Desde la computadora local (OSX), configure un demonio para escuchar en un puerto específico, a través de launchd(vea los enlaces a continuación). El proceso daemon simplemente llamará a pbcopy, que tomará todo lo que se haya pasado STDINy lo colocará en el portapapeles. Para hacer esto, necesita configurar un launchdarchivo plist. El mío se veía así:

<?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>

Por convención, el nombre del archivo plist debe ser el nombre de la etiqueta adjunto .plist, por lo que para el ejemplo anterior, sería local.pbcopy.9999.plist. Si desea utilizar un puerto que no sea 9999, simplemente cámbielo en todas partes (teniendo en cuenta que debe ser algo superior a 1024 y no debe ser un puerto conocido que ya esté utilizando). Una vez que todo funcione, puede quitar las teclas StandardOutPathy StandardErrorPathy las cadenas, ya que solo se necesitan para la depuración.

Para cargar el demonio, ejecute el siguiente comando:

$ launchctl load local.pbcopy.9999.plist

Puedes ver que está cargado o eliminarlo con los siguientes comandos:

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

Si desea que esto se cargue cada vez que inicie sesión, coloque el archivo plist en el ~/Library/LaunchAgentsdirectorio.

Nota: deberá configurar esto en cada host local en el que desee que funcione.

Reenvío de puertos SSH

Debido a que podría acceder a la máquina remota desde varias computadoras locales diferentes, no puedo codificar el envío de los datos en la máquina remota a un host específico. Para que esto sea lo menos doloroso y dinámico posible, he usado el reenvío de puertos SSH para crear un enlace dinámico desde la máquina remota de regreso a la computadora local (el cómo y el por qué de esto están más allá de esta respuesta; vea más abajo para obtener más información) . Específicamente, creo un enlace desde el puerto 9997 de las máquinas remotas al puerto 9999 de la computadora local, que ahora tiene un demonio escuchando, gracias a lo launchdanterior. Podría usar el puerto 9999 tanto en la máquina remota como en la computadora local, pero no es necesario.

Para configurar este túnel, ejecute el siguiente comando:

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

Puede acceder de forma remota a varias máquinas remotas diferentes con el mismo comando y todas funcionarán como se esperaba. Puede conectarse remotamente a la misma máquina remota varias veces con el mismo comando, y funcionará como se esperaba; vea la nota abajo.

Si no tiene ganas de escribir el -R 9997:localhost:9999en cada invocación de SSH que realice, puede poner la definición de reenvío remoto en el archivo de configuración de SSH para hacerlo automáticamente. Aquí hay un ejemplo de mi ~/.ssh/configarchivo:

Host ufo*
  RemoteForward 9997 localhost:9999

Con eso, cada vez que me SSH a un host cuyo nombre comienza con 'ufo', el reenvío remoto de 9997 a localhost: 9999 se configurará automáticamente. Consulte el enlace de la página del manual del archivo de configuración a continuación para obtener más opciones.

Enviando datos

En el extremo remoto, uso netcatpara enviar el contenido deseado de vuelta al demonio que escucha.

$ date | nc localhost 9997

Puedes complicarte tanto como quieras:

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

Incluso puede decidir dinámicamente si enviar o no datos, en función de si alguien está escuchando o no (probablemente haya una forma más eficiente de hacerlo, pero funciona):

#!/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

Observaciones y advertencias

Cosas que noté:

  • pbcopyjuega muy bien con Copy'em Paste
  • si inicia más de una sesión SSH con el mismo reenvío de puerto remoto a la misma máquina remota, solo la primera tendrá efecto; no se informarán errores de tipo "puerto duplicado" en ninguno de los extremos
  • De manera similar, si ingresa de forma remota desde varias computadoras locales diferentes a la misma máquina remota usando el mismo puerto remoto (por ejemplo, 9997), solo la primera tendrá algún efecto

Enlaces de referencia

Si no tiene ncen su host remoto, esto funciona, al menos en RHEL:echo "howdy" > /dev/tcp/localhost/9997
He usado esta solución durante más de 1 año, recientemente noté que no es compatible con Unicode. Por ejemplo, el portapapeles se llenó con test‚ûú abcafter echo "test➜ abc"|nc -w 0 localhost 9999, lo que significa que se convierte en ‚ûúen progreso, ¿alguien tiene una idea sobre esto?

pbcopy remoto para iTerm2 parece ser una pieza de software hecha especialmente para este problema.

Si usa iTerm2 , hay una manera más fácil. Esta funcionalidad está integrada en las capacidades de integración de Shell de iTerm2 a través del it2copycomando:

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

Para que funcione, elija el elemento de menú iTerm2-->Install Shell Integration mientras está conectado al host remoto, para instalarlo en su propia cuenta. Una vez hecho esto, tendrá acceso a it2copy, así como a un montón de otros comandos con alias que brindan una funcionalidad interesante.

Las otras soluciones aquí son buenas soluciones, pero esta es tan sencilla en comparación.

Puedes hacerlo

ssh -ttt user@location "ksh -c 'ls *'" | pbcopy
Necesito una solución para una sesión de shell interactiva; lo aclararé anteriormente.