mirror of
ssh://git.janware.com/janware/proj/jw-pkg
synced 2026-04-24 09:13:37 +02:00
run_cmd() is a thin layer over the public ExecContext API, which
falls back to using a Local instance if not other ExecContext is
specified explicitly. Both the default Local context as the
subsequent call to run() should have the same idea about
interactivity, so allowing to specify it in two parameters
("interactive" and "cmd_input") is a bad idea. Remove "interactive".
Signed-off-by: Jan Lindemann <jan@janware.com>
44 lines
1.6 KiB
Python
44 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from ...base import InputMode
|
|
from ...util import run_cmd
|
|
from ..SSHClient import SSHClient as Base
|
|
from .util import join_cmd
|
|
|
|
if TYPE_CHECKING:
|
|
from ...base import Result
|
|
|
|
class Exec(Base):
|
|
|
|
def __init__(self, *args, **kwargs) -> None:
|
|
self.__askpass: str|None = None
|
|
self.__askpass_orig: dict[str, str|None] = dict()
|
|
super().__init__(*args, **kwargs)
|
|
|
|
def __del__(self):
|
|
for key, val in self.__askpass_orig.items():
|
|
if val is None:
|
|
del os.environ[key]
|
|
else:
|
|
os.environ[key] = val
|
|
if self.__askpass is not None:
|
|
os.remove(self.__askpass)
|
|
|
|
def __init_askpass(self):
|
|
if self.__askpass is None and self.password is not None:
|
|
import sys, tempfile
|
|
prefix = os.path.basename(sys.argv[0]) + '-'
|
|
f = tempfile.NamedTemporaryFile(mode='w+t', prefix=prefix, delete=False)
|
|
os.chmod(f.name, 0o0700)
|
|
self.__askpass = f.name
|
|
f.write(f'#!/bin/bash\n\necho -n "{self.password}\n"')
|
|
f.close()
|
|
for key, val in {'SSH_ASKPASS': self.__askpass, 'SSH_ASKPASS_REQUIRE': 'force'}.items():
|
|
self.__askpass_orig[key] = os.getenv(key)
|
|
os.environ[key] = val
|
|
|
|
async def _run_ssh(self, cmd: list[str], cmd_input: bytes|None, *args, **kwargs) -> Result:
|
|
self.__init_askpass()
|
|
return await run_cmd(['ssh', self.hostname, join_cmd(cmd)], cmd_input=cmd_input, throw=False)
|