generated at
特定のssh鍵だけが登録されたssh-agentを簡単に起動する
ssh: Too many authentication failures の問題を避けるために、特定の鍵だけが登録されたssh-agentを簡単に起動したい。

使いたい鍵だけを登録したssh-agentを用意するPythonコード
run-ssh-agent.py
#!/usr/bin/env python """ $ python run-ssh-agent.py """ import os import sys import pickle import subprocess import logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger(__name__) KEY_AND_PASSPHRSE = { 'SERVER1.key': 'secret-passphrase-for-server1', } def register_keys(): # 鍵の登録先となるssh-agentを起動させる ret = subprocess.run('ssh-agent', stdout=subprocess.PIPE, encoding='ascii') logger.debug('start agent: %s', ret.stdout) env = os.environ.copy() # 起動したssh-agentのSSH_AGENT_PIDを環境変数に登録する env.update({ k: v.rstrip(';') for k, v in [part.split('=') for part in ret.stdout.split() if '=' in part] }) env['SSH_ASKPASS'] = os.path.abspath(sys.argv[0]) env['DISPLAY'] = ':999' logger.debug('env: %s', env) for keyfile, phrase in KEY_AND_PASSPHRSE.items(): env['PASSPHRASE'] = phrase p = subprocess.Popen( ['ssh-add', os.path.abspath(keyfile)], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, encoding='ascii', preexec_fn=os.setsid ) try: r = p.communicate(timeout=1) logger.debug('ssh-add return %s: %s', p.returncode, r) except subprocess.TimeoutExpired: logger.error('timeout') p.kill() logger.error(p.communicate()) break # 登録されている鍵の一覧を表示 p = subprocess.run( ['ssh-add', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, encoding='ascii', ) logger.debug('ssh-add -l\n%s', p.stdout) # 本来はagentは起動しっぱなしにしたいが、今回は実験を繰り返すためagentを終了させておく ret = subprocess.run(['ssh-agent', '-k'], env=env, stdout=subprocess.PIPE, encoding='ascii') logger.debug(ret.stdout) def main(): if os.environ.get('PASSPHRASE'): # ssh-addから呼ばれる、ssh-askpassとしての動作 print(os.environ['PASSPHRASE']) sys.exit(0) else: register_keys() if __name__ == '__main__': main()

この機能を一般化してOSSで公開した