linux终端cd未找到命令,为什么`which`命令不能用于`cd`?我也找不到`cd`的可执行文件!...

文章探讨了Linux终端中`cd`命令为何无法通过`which`找到可执行文件的原因。`cd`是一个shell内置命令,而非外部程序,因此`which`无法显示其路径。文章还讨论了shell内置命令的工作原理,并推荐使用`type -a`来查找内置命令。此外,文章提到了`cd`作为内置命令的必要性,因为它需要改变当前shell的执行环境,而非创建新的进程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

我尝试了which cd,它没有给出路径,而是返回退出代码1(用echo $?检查)。 coreutil cd本身正在工作,所以可执行文件应该在那里,对吧?我还为cd运行了find,但没有显示可执行文件。那怎么实现呢?

更新:

我不知道我是否应该在另一篇文章中提出这个问题,但由于我认为这里很好,我正在扩展(?)帖子……所以答案其实很简单,没有可执行文件 – 因为它是内置 – 但我发现一些内置(Fedora中的bash shell)有可执行文件!所以内置 – >我想,没有可执行文件是不对的?也许答案解释了内置实际上是什么(内置命令?),这实际上是这里的问题,而不是更多地关注cd …之前发布的一些好的链接表明内置不是程序……那么它们是什么?他们是如何工作的?它们只是shell的函数或线程吗?

最佳解决方案

命令cd不能是可执行文件

在shell中,cd用于“进入另一个目录”,或者更正式地用于更改curent工作目录(CWD)。作为外部命令实现它是不可能的:

该目录属于进程

curent工作目录是用于解释相对路径以获取可用于访问文件的完整路径的目录。相对路径在许多地方使用,一个过程中的解释不应影响另一个过程。因此,每个进程都有自己当前的工作目录。

cd是关于更改shell进程的当前工作目录,例如bash。

如果它是一个外部命令,路径中的可执行文件,运行该可执行文件将创建一个具有自己的工作目录的进程,而不会影响当前shell的进程。即使外部命令会改变它的目录,当外部进程退出时,该更改也会消失。

Shell内置命令

因此,为cd的任务运行外部命令是没有意义的。命令cd需要对当前运行的shell进程应用更改。

为此,它是shell的“builtin command”。

内置命令是与外部命令类似的命令,但是在shell中实现(因此cd不是coreutils的一部分)。这允许命令改变shell本身的状态,在这种情况下调用chdir()参见(参见man 2 chdir);

关于which

现在,标题问题的答案很简单:可执行命令which无法告诉我们cd是内置命令,因为可执行命令对内置命令一无所知。

替代type -a

作为which的替代品,您可以使用type -a;它可以看到可执行命令和内置函数;另外,它会看到别名和函数 – 也在shell中实现:

$ type -a cd

cd is a shell builtin

$ type -a type

type is a shell builtin

$ type -a which

which is /usr/bin/which

which is /bin/which

次佳解决方案

cd是一个内置的POSIX-mandated shell:

If a simple command results in a command name and an optional list of arguments, the following actions shall be performed:

If the command name does not contain any slashes, the first successful step in the following sequence shall occur:

If the command name matches the name of a utility listed in the following table, that utility shall be invoked.

cd

Otherwise, the command shall be searched for using the PATH…

虽然这没有明确说明它必须是内置,但规范接着说,在cd的描述中:

Since cd affects the current shell execution environment, it is always provided as a shell regular built-in.

从bash手册:

The following shell builtin commands are inherited from the Bourne Shell. These commands are implemented as specified by the POSIX standard.

cd cd [-L|[-P [-e]]] [directory]

我想你可以想到一个架构,其中cd不一定是内置的。但是,你必须看看内置意味着什么。如果你在shell中编写特殊代码来为某个命令做一些事情,你就会接近内置。你做的越多,只需要内置就越好。

例如,你可以让shell有IPC与子进程通信,并且会有一个cd程序,它会检查目录是否存在以及你是否有权访问它,然后与shell通信以告诉它改变它的目录。但是,您必须检查与您通信的进程是否是子进程(或者只与子进程通信的特殊方式,例如特殊文件描述符,共享内存等),如果进程实际上是运行受信任的cd程序或其他东西。这是一整套蠕虫。

或者您可以使用cd程序进行chdir系统调用,并启动一个新shell,其中所有当前环境变量都应用于新shell,然后在完成时以某种方式终止其父shell。

更糟糕的是,您甚至可以拥有一个系统,其中一个进程可以改变其他进程的环境(我认为从技术上讲,您可以使用调试器来完成此操作)。然而,这样的系统将非常非常脆弱。

您将发现自己添加了越来越多的代码来保护这些方法,而简单地将其作为内置函数则相当简单。

某些东西是可执行文件并不能阻止它成为内置函数。例证:

echo和test

echo和test是POSIX-mandated用途(/bin/echo和/bin/test)。然而,几乎所有流行的 shell 都有内置的echo和test。同样,kill也是内置的,可作为程序使用。其他包括:

sleep(不常见)

time

false

true

printf

但是,在某些情况下,命令不能是内置命令。其中之一是cd。通常,如果未指定完整路径,并且命令名称与内置命令名称匹配,则调用适合该命令的函数。取决于shell,内置的行为和可执行文件的行为可能不同(对于具有wildly differing behaviours的echo,这尤其是个问题。如果您想确定行为,最好使用完整的调用可执行文件路径,并设置像POSIXLY_CORRECT的变量(即使那时没有真正的保证)。

从技术上讲,没有什么可以阻止你提供一个也是一个shell的操作系统,并且每个命令都是内置的。接近这个极端的是单片BusyBox。 BusyBox是一个单独的二进制文件(取决于它所调用的名称)可以表现为任何over 240 programs,包括Almquist Shell(ash)。如果在运行BusyBox ash时取消设置PATH,则仍可访问BusyBox中可用的程序,而无需指定PATH。它们接近于shell内置,除了shell本身是内置于BusyBox的sort-of。

案例研究:Debian Almquist Shell(dash)

如果查看dash源代码,执行线程就是这样的(当然,在使用管道和其他东西时还会涉及其他功能):

main→cmdloop→evaltree→evalcommand

然后,evalcommand使用findcommand来确定命令是什么。如果它是内置的,then:

case CMDBUILTIN:

if (spclbltin > 0 || argc == 0) {

poplocalvars(1);

if (execcmd && argc > 1)

listsetvar(varlist.list, VEXPORT);

}

if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) {

if (exception == EXERROR && spclbltin <= 0) {

FORCEINTON;

break;

cmdentry.u.cmd是struct(struct builtincmd),其成员之一是功能指针,具有典型的main:(int, char **)的特征。 evalbltin函数调用(取决于内置函数是否为eval命令)evalcmd或此函数指针。实际功能在各种源文件中定义。例如,echo是:

int

echocmd(int argc, char **argv)

{

int nonl;

nonl = *++argv ? equal(*argv, "-n") : 0;

argv += nonl;

do {

int c;

if (likely(*argv))

nonl += print_escape_str("%s", NULL, NULL, *argv++);

if (nonl > 0)

break;

c = *argv ? ' ' : '\n';

out1c(c);

} while (*argv);

return 0;

}

本节中源代码的所有链接均为行number-based,因此它们可能会更改,恕不另行通知。

1 POSIX系统具有cd可执行文件。

边注:

在Unix和Linux上有很多优秀的帖子。处理shell行为的Linux。特别是:

If you haven’t noticed a pattern in the questions listed so far, nearly all of them involve Stéphane Chazelas.

第三种解决方案

您找不到cd的可执行文件,因为没有。

cd是shell的内部命令(例如bash)。

第四种方案

来自man which:

which returns the pathnames of the files (or links) which would be executed in the current environment, had its arguments been given as commands in a strictly POSIX-conformant shell. It does this by searching the PATH for executable files matching the names of the arguments. It does not follow symbolic links.

从which的描述可以看出,它只是检查PATH。因此,如果您实施了一些bash function,它将不会显示任何内容。最好使用type命令和which。

例如,在Ubuntu ls命令中别名为ls --color=auto。

$ type ls

ls is aliased to `ls --color=auto'

$ which ls

/bin/ls

如果您实现测试功能hello:

$ function hello() { for i in {1,2,3}; do echo Hello $i;done }

$ which hello

which什么都没有显示。但是type:

$ type hello

hello is a function

hello ()

{

for i in {1,2,3};

do

echo Hello $i;

done

}

在你的情况下:

$ type cd

cd is a shell builtin

这意味着cd是shell builtin,它位于bash内。所有bash builtins在man bash中描述,在SHELL BUILTIN命令中

SHELL BUILTIN COMMANDS

Unless otherwise noted, each builtin command documented in this section

as accepting options preceded by - accepts -- to signify the end of the

options. The :, true, false, and test builtins do not accept options

and do not treat -- specially. The exit, logout, break, continue, let,

and shift builtins accept and process arguments beginning with - with‐

out requiring --. Other builtins that accept arguments but are not

specified as accepting options interpret arguments beginning with - as

invalid options and require -- to prevent this interpretation.

参考资料

<think>好的,我现在需要帮助用户解决CRT链接虚拟机不到命令的问题。首先,用户提到的CRT应该是指SecureCRT,这是一个终端仿真软件,常用于连接远程服务器或虚拟机。用户遇到的问题是在连接后输入命令时提示不到命令,也就是“command not found”。我需要一步步分析可能的原因,并提供解决方案。 首先,我应该考虑最常见的原因。第一个可能性是命令确实不存在于虚拟机中。比如用户输入命令有安装,或者路径不对。例如,某些命令可能需要root权限,或者用户的环境变量配置有问题。 接下来,我需要分步骤思考可能的问题点: 1. **命令拼写错误**:用户可能输入了错误的命令名称,比如将ifconfig写成ipconfig,或者大小写错误。需要提醒用户检查拼写是否正确。 2. **命令未安装**:例如,在最小化安装的Linux系统中,可能有预装net-tools包,导致ifconfig命令不可用。这时候需要安装相应的软件包。 3. **环境变量问题**:用户的环境变量PATH可能有包含命令所在的目录。比如,某些自定义安装的软件可能不在标准路径中,导致系统不到。 4. **权限问题**:用户可能有执行该命令的权限,需要sudo或者切换到root用户。但通常权限问题会提示“Permission denied”而不是“command not found”,但也不排除某些情况。 5. **Shell配置问题**:用户的shell配置文件(如.bashrc、.bash_profile)可能被修改,导致PATH变量异常。或者用户可能使用了不同的shell,比如zsh,而配置未正确加载。 6. **虚拟机系统问题**:虚拟机的系统可能存在问题,比如文件系统损坏导致命令无法访问,或者动态链接库缺失。 7. **SecureCRT配置问题**:虽然较少见,但SecureCRT的终端设置可能导致某些命令无法正确识别,比如字符编码或终端类型设置错误。 接下来,我应该建议用户按照以下步骤排查: - **步骤1:检查命令拼写**:确认输入命令是否正确,比如检查是否存在拼写错误,或者尝试输入命令的绝对路径,如/bin/ls,看是否能执行。 - **步骤2:确认命令是否存在**:使用which或whereis命令命令的位置,例如`which ifconfig`或`whereis ifconfig`。如果不到,说明命令未安装。 - **步骤3:安装缺失的命令**:如果命令未安装,根据不同的Linux发行版使用包管理器安装。例如,在CentOS/RHEL中使用yum install net-tools,在Debian/Ubuntu中使用apt install net-tools。 - **步骤4:检查环境变量PATH**:使用`echo $PATH`查看PATH变量是否包含命令所在目录。如果缺失,可以临时添加或修改配置文件永久添加。 - **步骤5:检查权限和用户**:确认当前用户是否有权限执行该命令,或者尝试使用sudo执行。 - **步骤6:检查Shell配置**:查看用户的.bashrc或.bash_profile是否有异常设置,或者尝试切换shell测试。 - **步骤7:系统完整性检查**:如果以上步骤都无效,可能需要检查系统文件是否完整,或者考虑重新安装相关软件包。 另外,还需要考虑虚拟机本身的状态,比如是否正常启动,网络连接是否正常。如果虚拟机处于恢复模式或单用户模式,某些命令可能不可用。 最后,需要提醒用户根据具体情况进行排查,并给出具体的命令示例,以便用户操作。同时,注意不同Linux发行版的差异,比如包管理器的不同,安装命令的不同。</think>当使用SecureCRT连接虚拟机时出现“不到命令”(command not found)的问题,通常由以下原因导致。请按以下步骤排查: --- ### 一、常见原因及解决方案 #### 1. **命令未安装** - **现象**:输入基础命令(如 `ifconfig`、`netstat`)时报错。 - **原因**:虚拟机系统可能为最小化安装,未包含某些工具包。 - **解决**: - 安装对应工具包: ```bash # CentOS/RHEL sudo yum install net-tools # 安装ifconfig sudo yum install nc # 安装netcat # Debian/Ubuntu sudo apt install net-tools sudo apt install netcat ``` --- #### 2. **环境变量(PATH)配置错误** - **现象**:自定义安装的软件(如Java、Python)命令不可用。 - **原因**:命令路径未添加到 `PATH` 变量中。 - **解决**: 1. 临时修复(仅当前会话有效): ```bash export PATH=$PATH:/自定义路径 # 例如:/usr/local/java/bin ``` 2. 永久修复: 编辑 `~/.bashrc` 或 `~/.bash_profile`,添加: ```bash export PATH=$PATH:/自定义路径 ``` 保存后执行: ```bash source ~/.bashrc ``` --- #### 3. **命令拼写错误** - **现象**:输入命令时大小写错误(如 `Ipconfig` 代替 `ifconfig`)。 - **解决**: - 检查命令拼写。 - 使用 `Tab` 键自动补全。 --- #### 4. **权限问题** - **现象**:普通用户无法执行 `/sbin` 或 `/usr/sbin` 下的命令(如 `fdisk`)。 - **解决**: - 使用 `sudo` 提权: ```bash sudo fdisk -l ``` - 将用户添加到 `sudoers` 列表(需root权限)。 --- #### 5. **虚拟机系统损坏** - **现象**:所有命令均报错,或基础命令(如 `ls`、`cd`)不可用。 - **原因**:系统文件损坏或未挂载根目录。 - **解决**: - 重启虚拟机。 - 进入救援模式修复文件系统。 --- ### 二、高级排查方法 1. **检查命令是否存在**: ```bash which <命令名> # 查命令路径(例如:which ifconfig) whereis <命令名> # 搜索命令位置 ``` 2. **验证文件系统**: ```bash echo $PATH # 查看环境变量 ls -l /usr/bin/ls # 检查命令文件权限 ``` 3. **更新软件源**: ```bash # CentOS/RHEL sudo yum update # Debian/Ubuntu sudo apt update ``` --- ### 三、SecureCRT配置建议 1. **终端类型匹配**: - 检查SecureCRT的终端仿真设置是否为 `Linux` 或 `xterm`。 - 路径:`Options → Session Options → Terminal → Emulation`。 2. **字符编码**: - 确保编码为 `UTF-8`(尤其针对中文路径)。 - 路径:`Options → Session Options → Terminal → Appearance → Character Encoding`. --- ### 四、总结步骤 1. 确认命令拼写正确。 2. 通过 `which` 检查命令是否存在。 3. 安装缺失的软件包。 4. 检查 `PATH` 环境变量。 5. 使用 `sudo` 提权执行。 6. 验证系统完整性。 若问题仍未解决,请提供具体命令和虚拟机系统版本(如CentOS 7、Ubuntu 22.04),以便进一步分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值