将ssh远程命令记录到`bash_history`

Modified on: Sat, 30 Jun 2018 06:43:30 +0800

SSH允许远程用户在不交互式登录服务器的情况下发出一些命令,因为ssh用法的最后一行表示:

usage: ssh [-1246AaCfgKkMNnqsTtVvXxYy] [-b bind_address] [-c cipher_spec]
           [-D [bind_address:]port] [-E log_file] [-e escape_char]
           [-F configfile] [-I pkcs11] [-i identity_file]
           [-L [bind_address:]port:host:hostport] [-Q protocol_feature]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-R [bind_address:]port:host:hostport] [-S ctl_path]
           [-W host:port] [-w local_tun[:remote_tun]]
           [user@]hostname [command]

当使用远程命令调用ssh时,.bash_history文件不会更新(即,远程命令未添加到.bash_history)。我通过将以下命令添加到/etc/ssh/sshd_config来设法“模拟”此效果:

ForceCommand if [[ -z $SSH_ORIGINAL_COMMAND ]]; then bash; else printf "$SSH_ORIGINAL_COMMAND\n" >> .bash_history; bash -c "$SSH_ORIGINAL_COMMAND"; fi

上面的命令检查环境变量$SSH_ORIGINAL_COMMAND是否为空:

  • 如果是,则不会发出远程命令,我们只需运行bash
  • 否则,$SSH_ORIGINAL_COMMAND将添加到.bash_history,并且$SSH_ORIGINAL_COMMAND中的远程命令将被执行。

它按预期工作,但我需要更多:我希望将当前时间戳添加到.bash_history。为此,我将以下命令添加到/etc/ssh/sshd_config

ForceCommand if [[ -z $SSH_ORIGINAL_COMMAND ]]; then bash; else printf "#`date +%s`\n$SSH_ORIGINAL_COMMAND\n" >> .bash_history; bash -c "$SSH_ORIGINAL_COMMAND"; fi

但是当我尝试ssh到服务器时,我收到以下错误:

bash: -c: line 0: unexpected EOF while looking for matching `"'
bash: -c: line 1: syntax error: unexpected end of file
Connection to 127.0.0.1 closed.

如果我在#之前删除date +%s,它可以正常工作。但我需要在时间戳之前打印#,因为它是.bash_history文件的正确格式。

最佳答案

#中的sshd_config被解释为注释的开头,其后面的所有内容都将被忽略。虽然(根据sshd_config(5)""可用于引用包含空格的参数,但它们不引用#

这也解释了你得到的错误。 sshd仅将以下内容传递给bash

if [[ -z $SSH_ORIGINAL_COMMAND ]]; then bash; else printf "

找不到第二个",因为命令行在第一个命令行之后结束。

为防止出现这种情况,不得使用文字#

  • 因为无论如何都使用printf,使用其功能来使用反斜杠转义字符会派上用场。 #可以写成\x23(十六进制),\43(八进制),\u23(Unicode,十六进制,最多4个十六进制数字)或甚至\U23(Unicode,十六进制,最多8个十六进制数字)。这同样适用于echo -e。请注意,必须引用\,因此请使用"\43"'\43'\\43

  • 如果您不需要echoprintf,您可以获取bash(适用于zsh

  • 通过将所有功能放入脚本然后只需将#放入配置中,即可完全避免使用ForceCommand /path/to/script(文字或其他)

第二个选项还允许您通过更广泛地使用printf的格式选项来放弃date。而不是

printf "\x23`date +%s`\n$SSH_ORIGINAL_COMMAND\n" >> .bash_history

你可以写

date $'+\x23%s'"${SSH_ORIGINAL_COMMAND//%/%%}" >> .bash_history
作者:,Adaephon

相关问答

添加新评论