ssh kitten: Allow using python instead of the shell on the server
This commit is contained in:
parent
ee198ca863
commit
e9e8ef7210
@ -13,6 +13,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
|
|||||||
|
|
||||||
- diff kitten: Implement recursive diff over SSH (:iss:`3268`)
|
- diff kitten: Implement recursive diff over SSH (:iss:`3268`)
|
||||||
|
|
||||||
|
- ssh kitten: Allow using python instead of the shell on the server, useful if
|
||||||
|
the shell used is a non-POSIX compliant one, such as fish (:iss:`3277`)
|
||||||
|
|
||||||
- Add support for the color settings stack that XTerm copied from us without
|
- Add support for the color settings stack that XTerm copied from us without
|
||||||
acknowledgement and decided to use incompatible escape codes for.
|
acknowledgement and decided to use incompatible escape codes for.
|
||||||
|
|
||||||
|
|||||||
@ -54,7 +54,12 @@ type it each time::
|
|||||||
alias ssh="kitty +kitten ssh"
|
alias ssh="kitty +kitten ssh"
|
||||||
|
|
||||||
If for some reason that does not work (typically because the server is using a
|
If for some reason that does not work (typically because the server is using a
|
||||||
non POSIX compliant shell), you can use the following one-liner instead (it
|
non POSIX compliant shell), you can try using it with python instead::
|
||||||
|
|
||||||
|
kitty +kitten ssh use-python myserver
|
||||||
|
|
||||||
|
If that also fails, perhaps because python is not installed on the remote
|
||||||
|
server, use the following one-liner instead (it
|
||||||
is slower as it needs to ssh into the server twice, but will work with most
|
is slower as it needs to ssh into the server twice, but will work with most
|
||||||
servers)::
|
servers)::
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,33 @@ exec -a "-$shell_name" "$0"
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
PYTHON_SCRIPT = '''\
|
||||||
|
#!/usr/bin/env python
|
||||||
|
from __future__ import print_function
|
||||||
|
from tempfile import NamedTemporaryFile
|
||||||
|
import subprocess, os, sys, pwd, binascii, json
|
||||||
|
|
||||||
|
# macOS ships with an ancient version of tic that cannot read from stdin, so we
|
||||||
|
# create a temp file for it
|
||||||
|
with NamedTemporaryFile() as tmp:
|
||||||
|
tmp.write(binascii.unhexlify('{terminfo}'))
|
||||||
|
p = subprocess.Popen(['tic', '-x', '-o', os.path.expanduser('~/.terminfo'), tmp.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
stdout, stderr = p.communicate()
|
||||||
|
if p.wait() != 0:
|
||||||
|
getattr(sys.stderr, 'buffer', sys.stderr).write(stdout + stderr)
|
||||||
|
raise SystemExit('Failed to compile terminfo using tic')
|
||||||
|
command_to_execute = json.loads(binascii.unhexlify('{command_to_execute}'))
|
||||||
|
if command_to_execute:
|
||||||
|
os.execlp(command_to_execute[0], *command_to_execute)
|
||||||
|
try:
|
||||||
|
shell_path = pwd.getpwuid(os.geteuid()).pw_shell or '/bin/sh'
|
||||||
|
except KeyError:
|
||||||
|
shell_path = '/bin/sh'
|
||||||
|
shell_name = '-' + os.path.basename(shell_path)
|
||||||
|
os.execlp(shell_path, shell_name)
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
def get_ssh_cli() -> Tuple[Set[str], Set[str]]:
|
def get_ssh_cli() -> Tuple[Set[str], Set[str]]:
|
||||||
other_ssh_args: List[str] = []
|
other_ssh_args: List[str] = []
|
||||||
boolean_ssh_args: List[str] = []
|
boolean_ssh_args: List[str] = []
|
||||||
@ -150,20 +177,44 @@ def quote(x: str) -> str:
|
|||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
|
def get_posix_cmd(terminfo: str, server_args: List[str]) -> List[str]:
|
||||||
|
sh_script = SHELL_SCRIPT.replace('TERMINFO', terminfo, 1)
|
||||||
|
if len(server_args) > 1:
|
||||||
|
command_to_executeg = (quote(c) for c in server_args[1:])
|
||||||
|
command_to_execute = 'exec ' + ' '.join(command_to_executeg)
|
||||||
|
else:
|
||||||
|
command_to_execute = ''
|
||||||
|
sh_script = sh_script.replace('EXEC_CMD', command_to_execute)
|
||||||
|
return ['-t', server_args[0], sh_script] + server_args[1:]
|
||||||
|
|
||||||
|
|
||||||
|
def get_python_cmd(terminfo: str, server_args: List[str]) -> List[str]:
|
||||||
|
import json
|
||||||
|
hostname = server_args[0]
|
||||||
|
command_to_execute = server_args[1:]
|
||||||
|
script = PYTHON_SCRIPT.format(
|
||||||
|
terminfo=terminfo.encode('utf-8').hex(),
|
||||||
|
command_to_execute=json.dumps(command_to_execute).encode('utf-8').hex()
|
||||||
|
)
|
||||||
|
return ['-t', hostname, f'python -c "{script}"']
|
||||||
|
|
||||||
|
|
||||||
def main(args: List[str]) -> NoReturn:
|
def main(args: List[str]) -> NoReturn:
|
||||||
ssh_args, server_args, passthrough = parse_ssh_args(args[1:])
|
args = args[1:]
|
||||||
|
use_posix = True
|
||||||
|
if args and args[0] == 'use-python':
|
||||||
|
args = args[1:]
|
||||||
|
use_posix = False
|
||||||
|
ssh_args, server_args, passthrough = parse_ssh_args(args)
|
||||||
if passthrough:
|
if passthrough:
|
||||||
cmd = ['ssh'] + ssh_args + server_args
|
cmd = ['ssh'] + ssh_args + server_args
|
||||||
else:
|
else:
|
||||||
terminfo = subprocess.check_output(['infocmp']).decode('utf-8')
|
terminfo = subprocess.check_output(['infocmp']).decode('utf-8')
|
||||||
sh_script = SHELL_SCRIPT.replace('TERMINFO', terminfo, 1)
|
cmd = ['ssh'] + ssh_args
|
||||||
if len(server_args) > 1:
|
if use_posix:
|
||||||
command_to_executeg = (quote(c) for c in server_args[1:])
|
cmd += get_posix_cmd(terminfo, server_args)
|
||||||
command_to_execute = 'exec ' + ' '.join(command_to_executeg)
|
|
||||||
else:
|
else:
|
||||||
command_to_execute = ''
|
cmd += get_python_cmd(terminfo, server_args)
|
||||||
sh_script = sh_script.replace('EXEC_CMD', command_to_execute)
|
|
||||||
cmd = ['ssh'] + ssh_args + ['-t', server_args[0], sh_script] + server_args[1:]
|
|
||||||
os.execvp('ssh', cmd)
|
os.execvp('ssh', cmd)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user