Comment copier dans le presse-papiers OSX à partir d'un shell distant à l'aide de iTerm2?

5

À l'aide de iTerm2, je démarre une session SSH interactive sur une machine Linux distante (où elle pbcopyn'est pas disponible). Sur la machine Linux distante, j'aimerais capturer la sortie d'une commande quelconque (par exemple ls *.foo) et la faire apparaître comme par magie dans mon presse-papiers OSX, de sorte que lorsque je frappe +, vil apparaisse dans l'application OSX dans laquelle je viens de coller. Est-ce possible? J'ai essayé les codes d'échappement mentionnés sur la page iTerm2 doc et je ne peux pas les faire fonctionner.

Joe Casadonte
la source
@klanomath - merci, je vais en tenir compte (je ne suis pas sûr de vouloir configurer l'accès à ma machine via des clés SSH, bien qu'elle puisse être protégée par mot de passe, bien sûr).
Joe Casadonte
Cela nécessite X sur le serveur distant, qui n'existe pas, et XQuartz sur le serveur local, ce qui rend mon ordinateur très chaud. Mais c'est peut-être mon meilleur pari - merci!
Joe Casadonte
alors le commentaire de nbren12 à la deuxième réponse ! ;-)
klanomath
Déjà vu, cela nécessite toujours la configuration de clés SSH, et c'est le seul moyen de le faire, puisqu'un cas d'utilisation me fait entrer SSH dans la machine distante depuis une connexion VPN, donc pas statique IP ou nom d'hôte. Un autre problème est que j'ai des noms de compte d'utilisateur différents sur mes deux machines locales principales, mais je pourrais résoudre ce problème dans une variable d'environnement ou quelque chose du genre. Merci pour l'effort, cependant, je l'apprécie vraiment.
Joe Casadonte

Réponses:

4

Solution

Rassemblant de nombreuses informations provenant de plusieurs sources différentes, voici ce que j'ai proposé.

Démon local

À partir de l'ordinateur local (OSX), configurez un démon pour qu'il écoute sur un port spécifique, via launchd(voir les liens ci-dessous). Le processus démon appellera simplement pbcopy, ce qui prendra tout ce qui est passé dans STDINet le mettra dans le presse-papiers. Pour ce faire, vous devez configurer un launchdfichier plist. Le mien ressemblait à ceci:

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

Par convention, le nom du fichier plist devrait être le nom de l'étiquette avec le nom .plistajouté, donc pour l'exemple ci-dessus, ce le serait local.pbcopy.9999.plist. Si vous souhaitez utiliser un port autre que 9999, il suffit de le changer partout (en gardant à l'esprit qu'il doit être supérieur à 1024 et ne pas être un port bien connu que vous utilisez peut-être déjà). Une fois que vous avez des choses à travailler, vous pouvez supprimer les StandardOutPathet les StandardErrorPathclés et les chaînes, car ils sont seulement nécessaires pour le débogage.

Pour charger le démon, exécutez la commande suivante:

$ launchctl load local.pbcopy.9999.plist

Vous pouvez voir qu'il est chargé ou le supprimer à l'aide des commandes suivantes:

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

Si vous souhaitez que cela se charge à chaque fois que vous vous connectez, placez le fichier plist dans le ~/Library/LaunchAgentsrépertoire.

Remarque: vous devrez configurer ceci sur chaque hôte local sur lequel vous souhaitez que cela fonctionne.

SSH Port-Forwarding

Étant donné que je pourrais accéder à la machine distante à partir de plusieurs ordinateurs locaux différents, je ne peux pas coder en dur l'envoi des données sur la machine distante à un hôte spécifique. Pour rendre cela aussi indolore et dynamique que possible, j'ai utilisé le transfert de port SSH pour créer un lien dynamique entre la machine distante et l'ordinateur local (le comment et le pourquoi de ceci sont au-delà de cette réponse; voir ci-dessous pour plus d'informations) . Plus précisément, je crée un lien entre le port 9997 de la machine distante et le port 9999 de l'ordinateur local, sur lequel un démon écoute, grâce aux launchdéléments ci-dessus. Je pourrais utiliser le port 9999 sur la machine distante et sur l'ordinateur local, mais ce n'est pas nécessaire.

Pour configurer ce tunnel, exécutez la commande suivante:

$ ssh -R 9997:localhost:9999 [email protected]

Vous pouvez effectuer la commande à distance sur plusieurs machines distantes différentes avec la même commande et tout fonctionnera comme prévu. Vous pouvez effectuer plusieurs fois la télécommande sur le même ordinateur distant avec la même commande et cela fonctionnera comme prévu. voir note ci-dessous.

Si vous ne souhaitez pas saisir le caractère -R 9997:localhost:9999à chaque appel SSH, vous pouvez insérer la définition de transfert à distance dans le fichier de configuration SSH pour le faire automatiquement. Voici un exemple de mon ~/.ssh/configdossier:

Host ufo*
  RemoteForward 9997 localhost:9999

Avec cela, chaque fois que je SSH à un hôte dont le nom commence par 'ufo', la transmission à distance de 9997 à localhost: 9999 sera automatiquement configurée. Voir le lien de la page de manuel du fichier de configuration ci-dessous pour plus d'options.

Envoi de données

Sur le netcatserveur distant, je renvoie le contenu souhaité au démon d’écoute.

$ date | nc localhost 9997

Vous pouvez devenir aussi compliqué que vous le souhaitez:

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

Vous pouvez même décider de manière dynamique d'envoyer ou non des données, en fonction du fait que quelqu'un écoute ou non (il existe probablement un moyen plus efficace de le faire, mais cela fonctionne):

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

Observations et mises en garde

Choses que j'ai notées:

  • pbcopy joue bien avec Copy'em Paste
  • Si vous lancez plusieurs sessions SSH avec le même transfert de port distant sur le même ordinateur distant, seul le premier aura un effet quelconque. aucune erreur de type "port dupliqué" ne sera signalée à l'une ou l'autre extrémité
  • De même, si vous utilisez plusieurs ordinateurs locaux différents pour la même machine distante à l'aide du même port distant (par exemple, 9997), seul le premier aura un effet.

Liens de référence

Joe Casadonte
la source
1
Si vous n'avez pas ncsur votre hôte distant, cela fonctionne - au moins sur RHEL:echo "howdy" > /dev/tcp/localhost/9997
jaune pâle
1

Remote pbcopy pour iTerm2 semble être un logiciel spécialement conçu pour résoudre ce problème.

hyperknot
la source
0

Tu peux le faire

ssh -ttt user@location "ksh -c 'ls *'" | pbcopy
fd0
la source
J'ai besoin d'une solution pour une session shell interactive - je vais clarifier ci-dessus.
Joe Casadonte