• /usr/bin/cd 是什么鬼


    上文中曾讲到,我在我的 Mac 上发现很多和 Bash 内部命令同名的外部命令,在那 24 个外部命令中,我发现个奇怪的现象:它们中有 15 个居然是 Shell 脚本,更奇怪的是,居然是同一个 Shell 脚本的硬链接:

    $ find /usr/bin -inum 376183

    /usr/bin/alias

    /usr/bin/bg

    /usr/bin/cd

    /usr/bin/command

    /usr/bin/fc

    /usr/bin/fg

    /usr/bin/getopts

    /usr/bin/hash

    /usr/bin/jobs

    /usr/bin/read

    /usr/bin/type

    /usr/bin/ulimit

    /usr/bin/umask

    /usr/bin/unalias

    /usr/bin/wait

    看看脚本的内容:

    $ cat /usr/bin/cd

    #!/bin/sh

    # $FreeBSD: src/usr.bin/alias/generic.sh,v 1.2 2005/10/24 22:32:19 cperciva Exp $

    # This file is in the public domain.

    builtin `echo ${0##*/} | tr [:upper:] [:lower:]` ${1+"$@"}

    脚本只有一行,它的作用是什么?我分析了一下,当用户正常输入一个内部命令比如说 cd 时,Shell 肯定会把它当成内部命令执行,只有用户不小心把 cd 输入成 CD,由于 Mac 的文件系统不区分大小写,Shell 才会去执行这个外部的脚本。这个脚本拿到 $0 的值,也就是 /usr/bin/CD,砍掉路径,然后把大小字母替换成小写,也就是 cd,然后去执行 cd,同时带上参数。但我有几点想不通,这里的 builtin 完全是多余的,${1+"$@"} 也完全可以简写成 "$@",最重要的是,执行这些脚本是几乎没有任何意义的,因为 Shell 脚本是在当前 Shell 进程的新起的 Shell 进程里执行的,也就是说执行 CD / 相当于执行 bash -c 'cd /',当前 Shell 的工作目录其实并没有改变,除了 cd,其他命令也一样,虽然执行了,但完全没用,我再用 alias 和 unalias 演示一下:

    $ alias 'll=ls -l'

    $ Alias

    $ Unalias ll

    /usr/bin/Unalias: line 4: unalias: ll: not found

    $ alias

    alias ll='ls -l'

    这么做的出发点是什么,输入 CD 应该报错才对啊,不报错反而执行了没效果,多让人困惑的行为。

    于是我在网上查了一下,发现一篇日语的文章详详细细的介绍了这个脚本的来龙去脉。原来这个脚本存在的原因是:POSIX 标准要求操作系统要提供这 14 个内部命令对应的外部命令,以便 env、find、nice、nohup、time、xargs 这几个外部命令调用,比如 env cd。POSIX 又为什么这么规定,那就不知道了,但的确没卵用啊,怪不得 Linux 就没有遵守这个规范。

    最初这个脚本诞生于 FreeBSD 上,为什么加上 builtin 和用 ${1+"$@"} 都是因为 FreeBSD 操作系统的原因,那篇文章有讲。还有最初的脚本是没有  tr [:upper:] [:lower:] 这一部分的,FreeBSD 上不需要这个,苹果移植的时候考虑到自己的文件系统不区分大小写,故意做了改良。 

  • 相关阅读:
    聊天软件项目UDP升级版
    聊天软件项目TCP升级版
    JVM内存管理机制
    Java for循环的几种用法详解
    HashMap解决hash冲突的方法
    Hadoop NameNode 高可用 (High Availability) 实现解析
    Hadoop2.0NameNode HA和Federation实践
    Hadoop2.0中单点故障解决方案总结---老董
    HadoopHA简述
    数据库部分面试题
  • 原文地址:https://www.cnblogs.com/ziyunfei/p/4838235.html
Copyright © 2020-2023  润新知