如何查看/bin/sh指向哪里

6
我正在阅读/bin/sh和/bin/bash之间的区别,并发现了这个有趣的问题/答案:这里
我在回答中提出了同样的问题,并得到了更新后的答案:
如何在您的系统上找出/bin/sh指向的内容?
复杂之处在于/bin/sh可以是符号链接或硬链接。如果它是符号链接,则解决它的便携方式是:
> % file -h /bin/sh
> /bin/sh: symbolic link to bash 

如果它是一个硬链接,尝试:
> % find -L /bin -samefile /bin/sh 
> /bin/sh 
> /bin/bash

我尝试了这个方法,但遇到了问题,所以我想发一个单独的问题。

我从链接的答案中得到的结果:

>file -h /bin/sh
>/bin/sh: executable (RISC System/6000) or object module

>find -L /bin -samefile /bin/sh
>find: bad option -samefile

我漏掉了什么?我正在使用AIX操作系统:

>oslevel -s
7100-03-03-1415

1
看起来 /bin/sh 确实是您系统上的可执行文件,而不是符号链接。请记住,它不一定会“指向”其他 shell 可执行文件。显然,您的 find 实用程序不是 GNU find 实用程序,也与之不兼容。这对于商业 Unix 变体来说并不奇怪。 - arkascha
我在运行了man find之后搜索了“samefile”,但没有返回结果。这是否意味着我的“find”实用程序不支持该标志? - exit_1
1
AIX的“find”实用程序支持“-inum”。从“ls -i /bin/bash”获取“inode”,然后使用“find /bin -inum inode”并查看是否会出现“/bin/sh”。或者只需比较“ls -i /bin/sh /bin/bash”的“inodes”。 - alvits
@MadPhysicist 我非常理解那个问题。但是,OP执行的第一个测试无法区分硬链接和文件,这就是为什么该测试的结果显示为文件的原因。这就是我所说的。 - arkascha
1
硬链接是用于常规文件的文件系统指针结构。硬链接是对文件系统内部数据结构的引用。您无法区分常规文件和硬链接,因为所有常规文件都通过硬链接访问。符号链接是包含路径的文件,该路径用于指向另一个文件。符号链接中的数据不指向文件系统的内部数据结构。这就是为什么符号链接可以指向单独的文件系统,而硬链接不能的原因。 - Fred
显示剩余3条评论
8个回答

4
如果你需要编程地测试它们是否相同,可以使用stat查询/bin/shinode并与/bin/bashinode进行比较。
if [ $(stat -L -c %i /bin/sh) -eq $(stat -L -c %i /bin/bash) ]; then
    .....
fi

如果你只需要通过肉眼观察它们是否相同,运行 stat 命令并查看它们是否返回相同的 inode 数字即可。
stat -L -c %i /bin/sh
stat -L -c %i /bin/bash

3

既然你只在bin中搜索,你可以完全绕过find,直接检查shbash是否是同一文件的硬链接:

test /bin/sh -ef /bin/bash

或者

[ /bin/sh -ef /bin/bash ]

这种方法并不像在所有可能性上运行find那样可靠,但它是一个很好的开始。虽然AIX find不支持-samefile,但它支持-exec,可以与上面的命令相结合来模拟相同的功能:

find -L /bin -exec test /bin/sh -ef '{}' ';'

在我的观点中,编程测试中最好的答案。 - alvits
只是你答案的缩写表示法,我展示了如何将其插入到find中。 - Mad Physicist
这么多年我从未注意到test命令中的-ef操作数。谢谢,今天我学到了! - tripleee

2

检查GNU Bash

我将以不同的方式回答您的问题,因为查找sh是否为GNU Bash(或其他响应--version标志的内容)实际上比追踪inode更简单。 还有一种边缘情况,即shell被重命名而不是链接,这种情况下映射链接并不能真正帮助您找到答案。

例如,在macOS上查询/bin/sh

$ /bin/sh --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin16)
Copyright (C) 2007 Free Software Foundation, Inc.

或者,您可以使用grep(或类似工具)查找字符串bash以捕获退出状态。例如:

# Close stderr in case sh doesn't have a version flag.
if sh --version 2>&- | grep -qF bash; then
  echo "sh is bash"
else
  echo "sh isn't bash"
fi

当然,/bin/sh 可以是除了 bash 或原始 Bourne shell 之外的其他 shell,但这超出了您最初问题的范围。然而,许多 shell,如 ksh 和 tcsh,也支持版本标志,因此明智地使用 case 语句可以帮助您扩展测试以确切确定 /bin/sh 真正是哪个 shell 二进制文件。

1
您可以直接使用:

ls -l /bin/sh

2
嗨,我认为这个问题比你提供的解决方案要复杂一些。考虑扩展或删除。 - Eddy
这还不够复杂吗?楼主似乎在运行一个奇怪的系统,他并没有真正解释他的困惑。但这恰恰是我在寻找的答案,而且至少回答了标题中的问题。 - Deoxal

1
正如您在评论中提到的答案所说,-samefile不是find的标准功能。-inum也不是,它是根据显式给定的inode号进行搜索。但是,如果您的find支持它,请使用它。
POSIX的ls支持-i,它会打印出inode号。如果find没有-inum,您只需要遍历所有可能与/bin/sh硬链接的文件即可...
不过,在此之前,您可以检查该文件是否有任何其他硬链接,ls -l需要显示链接数:
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1029624 Nov  5 23:22 /bin/bash
           ^ here

当然,/bin/sh 没有必要链接到任何东西。它可以只是另一个程序。(或者甚至是一些其他文件的完全相同的副本,尽管我认为这不太可能。)

0

你也可以执行 readlink -f /bin/sh 命令。对我来说,它指向 /bin/dash


0

我真的看不出这个练习的意义。

/bin/sh 是一个 POSIX shell,而 bash 对 POSIX 标准有扩展,而 /bin/sh 不支持。

如果你正在编写一个 POSIX shell 脚本,请使用 /bin/sh。如果你正在编写一个 bash shell 脚本,请使用 bash

不要尝试编写一个将使用 /bin/sh 执行的 bash 脚本,并且不要尝试根据 /bin/sh(或当前解释器)链接到什么来编程地确定当前 shell 的能力。相反,使脚本可执行并为脚本使用正确的 #! 行。


0
在Mac上,你只需要执行la /private/var/select。输出的结果会类似于这样。
total 0
lrwxr-xr-x  1 root  wheel     9B Aug 24  2022 sh -> /bin/bash

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接