你了解你系统的bash吗

发布时间 2023-03-26 10:41:24作者: jinzi

    https://en.wikipedia.org/wiki/Unix_shell
    以下来自wiki

   1、 unix shell主要有以下的类别(unix系统有些系统也在使用gnu的bash) 

        Almquist shell   ( ash ): written as a BSD-licensed replacement for the Bourne Shell; often used in resource-constrained environments. The sh of   FreeBSD ,   NetBSD  (and their derivatives) are based on ash that has been enhanced to be   POSIX  conformant.

  • Busybox: a set of Unix utilities for small and embedded systems, which includes 2 shells: ash, a derivative of the Almquist shell; and hush, an independent implementation of a Bourne shell.
  • Debian Almquist shell  (dash): a modern replacement for ash in  Debian   and   Ubuntu

   2、Linux中主要有两种类型的shell:Bourne shell和C shell。

       Bourne shell有许多子类别:

  • POSIX shell ( sh)
  • Bourne shell ( sh )
  • Korn shell ( ksh )
  • Bourne Againshell ( bash )  gnu的shell
  • Z shell ( zsh )
  • Debian Almquist shell 

    一、实验环境
        [root@aozhejin2 /usr/local/src/shell]#cat /etc/redhat-release 
    CentOS Linux release 7.9.2009 (Core)
     [root@aozhejin2 /usr/local/src/shell]#uname -r
    3.10.0-1160.62.1.el7.x86_64

    二、确认本环境centos7下的bash程序的大体情况
     

    [root@aozhejin2 /usr/local/src/shell]#bash --version
    GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
    Copyright (C) 2011 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
        This is free software; you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.


    可执行bash程序的情况

    [root@aozhejin2 /usr/local/src/shell]#file /bin/sh
    /bin/sh: symbolic link to `bash'
    [root@aozhejin2 /usr/local/src/shell]#file /usr/bin/bash
    /usr/bin/bash: ELF 64-bit LSB executable, for GNU/Linux 2.6.32....
    [root@aozhejin2 /usr/local/src/shell]#file /bin/bash
    /bin/bash: ELF 64-bit LSB executable, x86-64 ....
    [root@aozhejin2 /usr/local/src/shell]#file /usr/bin/sh
    /usr/bin/sh: symbolic link to `bash'

        解释:
       1. /bin/sh 是指向 /bin/bash的符号链接
       2./usr/bin/bash 和/bin/bash 都是gnu
       3.bash是一个可执行的64位程序

     三、我们看看linux bash 的帮助(bash供应商为 gnu )

    [root@aozhejin2 /usr/local/src/makepackage/make-3.82]#bash --help
    GNU bash, version 4.2.46(2)-release-(x86_64-redhat-linux-gnu) Usage: bash [GNU long option] [option] ... bash [GNU long option] [option] script-file ... GNU long options:
    ....

       
     四、shell脚本开头的#!/bin/sh是什么?
        第一行 (#!/bin/bash 或 #!/bin/sh ) 有一个名字. 它叫 ‘she-bang‘(shabang).
          这源于令牌的串联 sharp (#) and bang (!).
         它也被称做 sharp-exclamation, sh-bang ,   hashbang,   poundbang  或 hash-pling .
        在计算中she-bang是由脚本开头的数字符号和感叹号(#!)组成的字符序列。
        
         /bin/bash是最常见的shell,用作linux系统用户登录的默认shell。它实际是gnu开发的Bourne-Again shell ,shell的名称是Bourne again shell的首字母缩写。
        详细可参考: https://en.wikipedia.org/wiki/Shebang_(Unix

         shabang的语法: 

     #! 解释器绝对路径

          解释一下:  # 字符英文翻译是hash, ! 翻译为exclamatory mark  ,他们都是Symbol(符号) 
          这个shabang还是很有历史的,可以查阅相关资料。
          #! 后面是系统当中存在的解析器比如: /usr/bin/bash 或/bin/sh、/usr/bin/python、/usr/bin/perl等
          那么组成之后大概是这个样子:

      #!/usr/bin/bash 或 #!/bin/sh 
       他们都指向的是/usr/bin/bash
    #!/usr/bin/python
    #!/usr/bin/perl
    #!/bin/cat
    #!/usr/bin/env python //使用env程序找到python解析器,执行python脚本  

         从这里可以看出,命令解析器可以是bash以外的其他解释程序.

         例子1:
        我们这里写一个python脚本验证一下sha-bang ,下面的程序就会寻找/usr/bin/路径下的 python

    #!/usr/bin/python
    import sys
    print("run...")

         运行

    [root@aozhejin2 /usr/local/src/shell]#ls /usr/bin/py (按ttab键列出下面的文件)
    pydoc      pyinotify  python     python2    python2.7
    [root@aozhejin2 /usr/local/src/shell]#chmod u+x pythonscript
    [root@aozhejin2 /usr/local/src/shell]#./pythonscript
    run ....

          例子2:

    #!/usr/bin/env perl
      print "foo!\n";

            运行

    [root@aozhejin2 /usr/local/src/shell]#chmod u+x testperl
    [root@aozhejin2 /usr/local/src/shell]#./testperl
    [root@aozhejin2 /usr/local/src/shell]#file testperl
    testperl: Perl script, ASCII text executable
    [root@aozhejin2 /usr/local/src/shell]#file -b testperl
    Perl script, ASCII text executable
    [root@aozhejin2 /usr/local/src/shell]#file -i testperl
    testperl: text/x-perl; charset=us-ascii


    五、写个Bourne-Again shell (gnu bash官方的名称 ) 的shell脚本测试一下:

    创建一个简单的脚本: testshell
    #!/bin/sh
       echo "run..."
    [root@aozhejin2 /usr/local/src/shell]#chmod 777 testshel

      [root@aozhejin2 /usr/local/src/shell]#./testshel
       run ...
       创建另外一个简单的脚本: testshell2

       #!/bin/bash 
       echo "run..."
      [root@aozhejin2 /usr/local/src/shell]#chmod 777 testshel2 [root@aozhejin2 /usr/local/src/shell]#./testshel2
    run ...

      [root@aozhejin2 /usr/local/src/shell]#file testshel2    //我们查看一下文件信息显示的是什么?
      testshel: Bourne-Again shell script , ASCII text executable

      [root@aozhejin2 /usr/local/src/shell]#chmod u-x testshel   //清除脚本权限依然可以执行
       [root@aozhejin2 /usr/local/src/shell]#ll
       total 4
       -rw-rwxrwx 1 root root 30 Mar 24 16:44 testshel
       [root@aozhejin2 /usr/local/src/shell]#./testshel
        run...

       testshell可以看出
       1. shell脚本执行会忽略第一行,即shabang行
       2. shabang行必须要指定解析器的绝对路径或利用env
       3. shabang组成 #! 解释器绝对路径

        我们再做一个测试:

     1 ls
     2 #!/bin/bash
     3    echo "运行..."
     4 #!/bin/bash
     5    echo "继续运行"
    继续测试上面的脚本,第4行 #!/bin/bash已经被解释为了注解,但是是不是第一行就必须是shabangt呢,我们看到
    ls首先被认为是linux执行程序被执行了,但是第二行开始因为有shabang,所以开始转交给bash来执行。
      [root@aozhejin2 /usr/local/src/shell]#./testshel 
     test  testshel  
       运行...
       继续运行
    注意: test testshell 是ls的内容,当前目录下有两个文件

     六、bash源码分析

        请从 https://mirror.vern.cc/gnu/bash/   下载
    七、shebang的历史

      shebang 由Dennis Ritchie在贝尔实验室的第 7 版第 8 版之间引入。它也被添加到伯克利计算机科学研究所的BSD版本中(出现在 2.8BSD 中,默认情况下由 4.2BSD 激活)。由于 AT&T Bell Laboratories Edition 8 Unix 及更高版本未向公众发布,因此此功能首次广为人知的出现是在 BSD 上。

       缺少解释器指令,但支持 shell 脚本,这在1979 年第 7 版 Unix的文档中很明显, 它描述了 Bourne shell 的一种功能,其中具有执行权限的文件将由 shell 专门处理,这将(有时取决于脚本中的初始字符,例如“:”或“#”)生成一个子shell,该子shell将解释并运行文件中包含的命令。在此模型中,如果从 Bourne shell 中调用脚本,则脚本的行为将与其他命令相同。尝试通过操作系统自己的exec()系统陷阱直接执行此类文件会失败,从而阻止脚本像正常系统命令一样正常运行。

    在后来的类 Unix 系统版本中,这种不一致被消除了。Dennis Ritchie在 1980 年 1 月为Version 8 Unix引入了对解释器指令的内核支持。

    英文原文

    From uucp Thu Jan 10 01:37:58 1980
    >From dmr Thu Jan 10 04:25:49 1980 remote from research

    The system has been changed so that if a file being executed
    begins with the magic characters #! , the rest of the line is understood
    to be the name of an interpreter for the executed file.
    Previously (and in fact still) the shell did much of this job;
    it automatically executed itself on a text file with executable mode
    when the text file's name was typed as a command.
    Putting the facility into the system gives the following
    benefits.

    1) It makes shell scripts more like real executable files,
    because they can be the subject of 'exec.'

    2) If you do a 'ps' while such a command is running, its real
    name appears instead of 'sh'.
    Likewise, accounting is done on the basis of the real name.

    3) Shell scripts can be set-user-ID.[a]

    4) It is simpler to have alternate shells available;
    e.g. if you like the Berkeley csh there is no question about
    which shell is to interpret a file.

    5) It will allow other interpreters to fit in more smoothly.

    To take advantage of this wonderful opportunity,
    put

      #! /bin/sh

    at the left margin of the first line of your shell scripts.
    Blanks after ! are OK.  Use a complete pathname (no search is done).
    At the moment the whole line is restricted to 16 characters but
    this limit will be raised.

    该功能的创建者没有给它命名,但是:

    英文原文

    From:"Ritchie,DennisM(Dennis)**CTR**"<dmr@[redacted]>
    To:<[redacted]@talisman.org>
    Date:Thu, 19 Nov 2009 18:37:37 -0600
    Subject:RE:Whatdo-you-callyour#!<something>line?

    I can't recall that we ever gave it a proper name.
    It was pretty late that it went in--I think that I
    got the idea from someone at one of the UCB conferences
    on Berkeley Unix; I may have been one of the first to
    actually install it, but it was an idea that I got
    from elsewhere.

    As for the name: probably something descriptive like
    "hash-bang" though this has a specifically British flavor, but
    in any event I don't recall particularly using a pet name
    for the construction.

      内核对解释器指令的支持被传播到其他版本的 Unix,并且可以在fs/binfmt_script.c的 Linux 内核源代码中看到一种现代实现。
      查看:

      https://github.com/torvalds/linux/blob/master/fs/binfmt_script.c

        这种机制允许脚本在几乎任何普通编译程序可以使用的上下文中使用,包括作为完整的系统程序,甚至作为其他脚本的解释器。但需要注意的是,某些早期版本的内核支持将解释器指令的长度限制为大约 32 个字符(在其第一个实现中仅为 16 个字符),无法将解释器名称与指令中的任何参数分开,或者有其他怪癖. 此外,一些现代系统允许出于安全目的限制或禁用整个机制(例如,许多系统上的脚本已禁用 set-user-id 支持)。

     

       请注意,即使在内核完全支持#! magic number,一些缺少解释器指令的脚本(尽管通常仍然需要执行权限)凭借 Bourne shell 的遗留脚本处理仍然可以运行,仍然存在于它的许多现代后代中。然后脚本由用户的默认 shell 解释。

     

    其它参考资料:
       https://www.gnu.org/software/bash/

      官方:
      https://www.gnu.org/software/bash/manual/
     wiki解释
     https://en.wikipedia.org/wiki/Bourne_shell
     pdf版本帮助
     https://www.gnu.org/software/bash/manual/bash.pdf
     html版本帮助
     https://www.gnu.org/software/bash/manual/bash.html

     https://www.learnlinux.org.za/courses/build/fundamentals/ch04s04.html
    https://en.wikipedia.org/wiki/Directive_(programming)
    https://en.wikipedia.org/wiki/Shebang_(Unix)  

     http://tldp.org/LDP/abs/html/sha-bang.html
    https://books.google.com/books?id=WPXkgFRd4OEC&q=sha-bang&pg=PA5#v=snippet&q=sha-bang&f=false

    http://www.pixelbeat.org/programming/shell_script_mistakes.html

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html 

    https://developers.slashdot.org/story/16/07/14/1349207/the-slashdot-interview-with-larry-wall