Como posso usar meu cliente Emacs local como o $ EDITOR para máquinas remotas que eu acesso através do TRAMP?
44
Costumo usar o TRAMP para gerenciar vários servidores remotos, tanto para editar arquivos quanto para executar shells remotos shell-mode. No entanto, isso não funciona quando um comando usa a EDITORvariável para editar um arquivo, crontab -eespecialmente porque shell-modeé um terminal "burro" que não suporta a execução de outro editor dentro dele.
Localmente, faço isso com uma chamada apropriada, emacsclientque abre um novo buffer e facilita a vida. Infelizmente, isso não funciona na máquina remota.
Eu acho que eu poderia usar ed. (Hah!)
Como posso configurar um controle remoto EDITORque permita editar arquivos com minha instância local do Emacs?
[NOTA] esta resposta foi fortemente editada para acompanhar as atualizações dos with-editordesenvolvimentos. A maioria dos comentários provavelmente não fará mais sentido. Existem alguns novos comentários que fazem sentido.
O Magit contém uma biblioteca chamada with-editordisponível em https://github.com/magit/with-editor, que permite usar o Emacs local como um $ EDITOR em máquinas remotas através do TRAMP.
Em seguida, basta começar shell, eshellou ansi-terme faça o seguinte:
M-x with-editor-export-editor
Ele perguntará em qual $ EDITOR você está interessado, basta pressionar Enter para a EDITORvariável padrão . Depois, dentro do shell, você pode digitar crontab -ee editar seu crontab no emacs. Pressione C-c C-cpara salvar o crontab ou C-c C-kpara cancelar a edição.
Você poderia elaborar como essa with-editorbiblioteca se relaciona com a pergunta? Soa útil
Malabarba
@Silex: Eu precisaria definir a $EDITORvariável como algo na máquina remota para que isso funcione? Isso apenas se encaixa emacsclient?
Tikhon Jelvis
Mas sim, isso parece exatamente o que eu quero. Vou tentar de alguma forma - presumo que ele possa ser instalado sozinho, sem o restante da ramificação?
Tikhon Jelvis
1
@TikhonJelvi: certamente será instalável por si só, mas por enquanto é apenas parte disso git-modes. Estou acompanhando essa biblioteca de perto e é apenas que seu autor (@tarsius) está ocupado com o lançamento do magit, mas eventualmente ele seria um pacote próprio. Sobre o $ EDITOR, você não precisa configurá-lo para nada, é feito quando necessário quando você executa qualquer comando que o utilize. O Magit usa essa biblioteca com $ GIT_EDITOR.
Silex 9/10
1
Observe que isso irá parar de funcionar após o sshing para um controle remoto a partir de um shell-mode/ term-modebuffer existente . Isso pode ser solucionado com algumas configurações adicionais, consulte emacs.stackexchange.com/questions/5589/… . Se você conseguir fazê-lo funcionar, relate suas descobertas em github.com/magit/magit/issues/1638 .
tarsius
1
Disclaimer: Eu não tentei isso.
Você pode obter parte do caminho com uma saída de comando de observação de função para um comando para abrir o arquivo usando TRAMP. Falha de segurança? Sim. Funcional? Provavelmente.
Use um shell-modegancho para adicionar um gancho para after-change-hooknos shell-mode. Este gancho observa uma sequência específica. Exemplo:
Em seguida, ele usa tramp-find-filepara abrir o arquivo. Isso é relativamente seguro porque a ÚNICA COISA que o controle remoto pode fazer é acionar a tramp-find-file. Uma confirmação primeiro seria boa, mas opcional.
Quando a edição termina, outro gancho pode acionar a saída do programa fictício (por exemplo, enviando C-c).
O pior caso (por segurança) é que eles encontram uma maneira de executar código arbitrário. Se você tiver variáveis de buffer definidas para sempre avaliar, um invasor mal-intencionado poderá substituir configurações importantes sem o seu conhecimento. Eles também podem iniciar um ataque de negação de serviço fazendo com que muitos buffers sejam abertos. As confirmações provavelmente podem impedir todas as opções acima.
O programa no controle remoto pode ser implementado trivialmente em C (ou em qualquer outro idioma).
Eu tenho um pequeno script no meu caminho no host remoto em ~/bin/ec, abreviação de emacsclient.
#!/bin/bash
params=()
for p in "$@"; do
if [ "$p" == "-n" ]; then
params+=( "$p" )
elif [ "${p:0:1}" == "+" ]; then
params+=( "$p" )
else
params+=( "/ssh:z:"$(readlink -f $p) )
fi
done
emacsclient --server-file=$HOME/.emacs.d/server/server "${params[@]}"
Este script passa -ne +args inalterados para o emacsclient, caso contrário, os args são tratados como arquivos para o seu Emacs local abrir. Cada arquivo é prefixado com o protocolo TRAMP e o host para que o Emacs saiba como abri-lo. Você pode mudar ssh:para um protocolo TRAMP diferente, se preferir.
Você deve substituir zpelo nome do host da sua máquina remota. Isso é usado pelo Emacs local para se conectar via TRAMP. (Você pode usar hostnameaqui por generalidade. Prefiro usar pequenas entradas como zno meu local ssh_configpor questões de brevidade, e o controle remoto não faz ideia de que estou fazendo isso. Experimente!)
Uso:
ec file no shell remoto abre o arquivo no Emacs local e aguarda
ec -n file no shell remoto abre o arquivo no Emacs local e retorna
export EDITOR=~/bin/ecno controle remoto .bashrcfaz a mágica acontecer
Para garantir que meu serverarquivo seja bom, eu tenho isso no meu local .emacs, novamente usando o pequeno nome de host z:
(setq server-use-tcp t
server-port 9999)
(defun server-start-and-copy ()
"Start server and copy server file to remote box."
(interactive)
(server-start)
(copy-file "~/.emacs.d/server/server" "/z:.emacs.d/server/server" t)
(chmod "/z:.emacs.d/server/server" (string-to-number "644" 8))
)
(add-hook 'emacs-startup-hook 'server-start-and-copy)
A porta 9999 é um RemoteForward. Coloquei isso no meu local ~/.ssh/ssh_configpara automatizar o encaminhamento, além do material do ControlMaster para obter velocidade.
Host z
HostName dev.example.com
User dev
ControlMaster auto
ControlPath ~/.ssh/z.sock
RemoteForward 9999 localhost:9999
Por fim, verifique se o TRAMP conhece o seu ssh_configse você o usar:
Você quer dizer voltar ao servidor remoto para o cliente em que o Emacs está executando? Isso geralmente não é possível.
Gilles 'SO- stop be evil'
Bem, se você não pode alcançar o cliente onde o Emacs está executando, é impossível fazer qualquer coisa.
Artagnon # 23/14
2
Você pode perguntar ao ssh, através de ~ / .ssh / config, para sempre encaminhar o ouvinte local do ssh para uma porta na máquina remota. Você provavelmente também desejaria encaminhar seu agente ssh, embora as opiniões variem quanto à segurança. Isso permitirá que você volte ao fazer EDITOR = "ssh $ user @ localhost: 1234 ..."
Ben Hyde
Outra opção talvez estaria escrevendo um pequeno wrapper para chamada edit-server.el
Realmente surpreso, ninguém mencionou sshfsainda. Isto é o que eu costumo fazer quando for remoto:
1) multi-term; sshfs user@host:/dir/i/want/ /mnt/point/on/my/machine
2) open whatever I want to edit in my local emacs
3) get-term; ssh user@host to launch executables etc
Embora multi-termnão sincronize o diretório de trabalho local com o diretório remoto, ele supera todas as outras soluções que tentei de longe. Embora o rastreamento de diretórios seja um recurso bem-vindo, com certeza.
with-editor
biblioteca se relaciona com a pergunta? Soa útil$EDITOR
variável como algo na máquina remota para que isso funcione? Isso apenas se encaixaemacsclient
?git-modes
. Estou acompanhando essa biblioteca de perto e é apenas que seu autor (@tarsius) está ocupado com o lançamento do magit, mas eventualmente ele seria um pacote próprio. Sobre o $ EDITOR, você não precisa configurá-lo para nada, é feito quando necessário quando você executa qualquer comando que o utilize. O Magit usa essa biblioteca com $ GIT_EDITOR.shell-mode
/term-mode
buffer existente . Isso pode ser solucionado com algumas configurações adicionais, consulte emacs.stackexchange.com/questions/5589/… . Se você conseguir fazê-lo funcionar, relate suas descobertas em github.com/magit/magit/issues/1638 .Disclaimer: Eu não tentei isso.
Você pode obter parte do caminho com uma saída de comando de observação de função para um comando para abrir o arquivo usando TRAMP. Falha de segurança? Sim. Funcional? Provavelmente.
Use um
shell-mode
gancho para adicionar um gancho paraafter-change-hook
nosshell-mode
. Este gancho observa uma sequência específica. Exemplo:Em seguida, ele usa
tramp-find-file
para abrir o arquivo. Isso é relativamente seguro porque a ÚNICA COISA que o controle remoto pode fazer é acionar atramp-find-file
. Uma confirmação primeiro seria boa, mas opcional.Quando a edição termina, outro gancho pode acionar a saída do programa fictício (por exemplo, enviando
C-c
).O pior caso (por segurança) é que eles encontram uma maneira de executar código arbitrário. Se você tiver variáveis de buffer definidas para sempre avaliar, um invasor mal-intencionado poderá substituir configurações importantes sem o seu conhecimento. Eles também podem iniciar um ataque de negação de serviço fazendo com que muitos buffers sejam abertos. As confirmações provavelmente podem impedir todas as opções acima.
O programa no controle remoto pode ser implementado trivialmente em C (ou em qualquer outro idioma).
fonte
https://stackoverflow.com/questions/2231902/originate-edit-of-remote-file-using-emacs-tramp-from-ssh-session tem uma resposta aceita bastante simples que equivale a
e depois use
Também há https://stackoverflow.com/questions/12546722/using-emacs-server-and-emacsclient-on-other-machines-as-other-users que é mais complexo, mas onde as respostas também (aproximadamente) são similares bases.
fonte
Eu tenho um pequeno script no meu caminho no host remoto em
~/bin/ec
, abreviação de emacsclient.Este script passa
-n
e+
args inalterados para o emacsclient, caso contrário, os args são tratados como arquivos para o seu Emacs local abrir. Cada arquivo é prefixado com o protocolo TRAMP e o host para que o Emacs saiba como abri-lo. Você pode mudarssh:
para um protocolo TRAMP diferente, se preferir.Você deve substituir
z
pelo nome do host da sua máquina remota. Isso é usado pelo Emacs local para se conectar via TRAMP. (Você pode usarhostname
aqui por generalidade. Prefiro usar pequenas entradas comoz
no meu localssh_config
por questões de brevidade, e o controle remoto não faz ideia de que estou fazendo isso. Experimente!)Uso:
ec file
no shell remoto abre o arquivo no Emacs local e aguardaec -n file
no shell remoto abre o arquivo no Emacs local e retornaexport EDITOR=~/bin/ec
no controle remoto.bashrc
faz a mágica acontecerPara garantir que meu
server
arquivo seja bom, eu tenho isso no meu local.emacs
, novamente usando o pequeno nome de hostz
:A porta 9999 é um RemoteForward. Coloquei isso no meu local
~/.ssh/ssh_config
para automatizar o encaminhamento, além do material do ControlMaster para obter velocidade.Por fim, verifique se o TRAMP conhece o seu
ssh_config
se você o usar:fonte
Pode exigir alguns ajustes, mas aqui está a idéia:
fonte
Harold Abnabit veio com essa abordagem 1 :
http://blog.habnab.it/blog/2013/06/25/emacsclient-and-tramp/
1 baseado em um artigo anterior de Ryan Barrett (ao qual ele vincula).
FWIW, também há https://stackoverflow.com/q/5154224/324105 no qual Petri Lehtinen criou https://gist.github.com/akheron/850795 . Imagino que as soluções mais complexas sejam melhores, mas uma abordagem muito simples ainda pode ser interessante.
fonte
Realmente surpreso, ninguém mencionou
sshfs
ainda. Isto é o que eu costumo fazer quando for remoto:Embora
multi-term
não sincronize o diretório de trabalho local com o diretório remoto, ele supera todas as outras soluções que tentei de longe. Embora o rastreamento de diretórios seja um recurso bem-vindo, com certeza.fonte