Cat 命令输出在 * 字符方面存在异常变化

Cat 命令输出在 * 字符方面存在异常变化

我在 vSphere 下运行的相当标准的 Ubuntu 11.04 安装上运行以下命令:

sudo cat /home/*/.ssh/authorized_keys

基本上,我使用 puppet 进行 ssh 密钥管理,并希望确保密钥存在。这个简单命令的不寻常之处在于,仅显示两个用户的密钥(如果相关,则显示在该用户上创建的第一个和第三个用户),而 * 应该捕获 7 或 8 个用户的家之类的信息。

有趣的是,如果我跑

sudo cat /home/user.name/.ssh/authorized_keys

其中 user.name 是随机用户的名称(不是已经显示的两个用户之一),我不仅从 cat 获得了正确的输出,而且下次运行时

sudo cat /home/*/.ssh/authorized_keys

输出显示 3 个密钥文件!两个文件是之前显示的两个用户的文件,第三个文件是我刚刚手动查看的密钥文件的用户的文件。

我可以继续玩这个“游戏”,每次我手动指定一个用户然后运行 ​​ 命令时,之前查看的用户就会显示在通配输出中。对我来说,这是一种不寻常的行为,尤其是对于标准的 Ubuntu 映像而言。我是不是漏掉了什么?* 扩展或 cat 的特殊属性?

编辑:忘记提到,如果我将 ssh 会话保留到服务器,此行为将“重置”。我的意思是,我可以通过 SSH 注销并重新登录,然后我又回到了起始状态(仅显示两个带有 * 的用户帐户)。

答案1

记住命令行被解析并且通配符被替换它被执行了。

如果您指定用户名,那么 sudo ... 命令可以看到该文件,因为它以 root 身份访问该文件。

当你输入“*”时,你的 USER shell 会将其扩展为路径它可以看到,嗯...允许当前用户搜索子目录的路径。

您可以尝试将路径字符串括在单引号中以防止扩展,但我不确定这是否有效,因为大多数 unix 程序都希望 shell 扩展通配符,因此不会自己执行通配符操作。

编辑:关于如何实现读取所有用户的授权密钥文件的目标的想法:

sudo find /home -name "authorized_keys" -exec cat "{}" \; > all_the_data

可能很粗糙,但它会起作用,因为您是以 root 身份而不是用户身份执行文件搜索。

我想换一种方式:

sudo 'find /home -name "authorized_keys" -print0 | xargs -0 cat' > all_the_data

那个在进程数上更好,因为它累积了所有的文件名,然后对它们进行“cat”......但我喜欢第一个,不需要特殊引用。

由于管道命令,整个命令必须用引号(单引号或其他引号)括起来。 find 和 xargs 命令都必须以 root 身份执行。 是的,比第一个更复杂。

答案2

我无法直接解释为什么通配符会执行其所执行的操作,但我知道如何重写脚本来完成您想要的操作:

对于 /home/* 中的 i;如果 [ -d "/home/${i}" ],则执行;然后 sudo cat "/home/${i}/.ssh/authorized_keys";fi;完成

我不知道 bash 的任何功能会导致它根据过去运行的命令以不同的方式进行匹配,因此它可能是一个错误或一个非常深埋的(未记录的)功能。我从不对目录使用 globs;我总是使用 find 命令进行 for 循环。我不相信 globs 会对任何包含 的模式做正确的事情/*/

相关内容