From dea47d7b0670402be718aa31be157f63b39580a9 Mon Sep 17 00:00:00 2001 From: nicholasyang Date: Thu, 2 Nov 2023 15:27:31 +0800 Subject: [PATCH] Fix (Experimental): sh: raise AuthorizationError and generate diagnose messages when ClusterShell fails with 255 --- crmsh/sh.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/crmsh/sh.py b/crmsh/sh.py index aa2fa04174..89561507bc 100644 --- a/crmsh/sh.py +++ b/crmsh/sh.py @@ -25,6 +25,7 @@ import socket import subprocess import typing +from io import StringIO from . import constants from .pyshim import cache @@ -45,15 +46,26 @@ def __init__(self, msg, cmd): class AuthorizationError(Error): def __init__(self, cmd: str, host: typing.Optional[str], user: str, msg: str): super().__init__( - 'Failed to run command on {optional_user}{host}: {msg}: {cmd}'.format( + 'Failed to run command {cmd} on {optional_user}{host}: {msg} {diagnose}'.format( optional_user=f'{user}@' if user is not None else '', - host=host, msg=msg, cmd=cmd + host=host, msg=msg, cmd=cmd, + diagnose=self.diagnose(), ), cmd ) self.host = host self.user = user + @staticmethod + def diagnose() -> str: + if user_of_host.instance().use_ssh_agent(): + with StringIO() as buf: + if 'SSH_AUTH_SOCK' not in os.environ: + buf.write('Environmental variable SSH_AUTH_SOCK does not exists.') + if 'SUDO_USER' in os.environ: + buf.write(' Please make sure environmental variables are preserved across sudo calls.') + return buf.getvalue() + class CommandFailure(Error): def __init__(self, cmd: str, host: typing.Optional[str], user: typing.Optional[str], msg: str): @@ -309,7 +321,7 @@ def subprocess_run_without_input(self, host: typing.Optional[str], user: typing. local_user, remote_user = self.user_of_host.user_pair_for_ssh(host) result = self.local_shell.su_subprocess_run( local_user, - 'ssh {} {} {}@{} sudo -H -u {} {} /bin/sh'.format( + 'ssh {} {} -o BatchMode=yes {}@{} sudo -H -u {} {} /bin/sh'.format( '-A' if self.forward_ssh_agent else '', constants.SSH_OPTION, remote_user, @@ -319,6 +331,7 @@ def subprocess_run_without_input(self, host: typing.Optional[str], user: typing. constants.SSH_OPTION, ), input=cmd.encode('utf-8'), + start_new_session=True, **kwargs, ) if self.raise_ssh_error and result.returncode == 255: @@ -463,4 +476,4 @@ def subprocess_run_without_input(self, host: str, user: typing.Optional[str], cm def cluster_shell(): - return ClusterShell(LocalShell(), user_of_host.instance()) + return ClusterShell(LocalShell(), user_of_host.instance(), raise_ssh_error=True)