认识bash shell

认识 bash shell

Bash shell

我们知道管理计算机硬件的是kernel,而我们user是通过shell和kernel进行沟通的,那到底什么是shell,什么是bash呢?

什么是shell?

你可以理解shell就是指令,没错,就是指令,这指令是用来干嘛的呢?当然是用来控制计算值按照我们想要的动作工作啦,也就是说其实shell就是用户用来控制计算机工作的指令。

我们知道直接控制计算机硬件的是kernel,而我们用户则可以通过shell控制kernel从而间接地控制硬件工作。

什么是bash?

Bash是一个命令处理器,通常运行于文本窗口中,并能执行用户直接输入的命令。全称: Bourne-Again Shell。有没有发现什么,没错,bash也是一种shell,其实bash只是shell的一种,而我们学习的Linux上的shell就是bash。

我们查看/etc下的shells文件就可以知道linux下可以使用的各种shell。

不同的shell的功能是差不多的,只是使用语法有不同而已。我们学习使用最广泛的bash。

bash shell的内建命令:type

通过 type 指令 例如 type cd 可以知道一条指令是不是bash的内建指令

shell的变量功能

通过使用变量,我们可以用一个简单的内容来表示复杂的内容或者是变化的内容

例如前面讲过的PATH就是一个变量 ,我们通过echo $PATH就可以打印这个变量。 为了区别与自订变量的不同,环境变量通常以大写字符来表示呢!

变量的取用与设定

通过echo可以取用变量,echo $变量名

通过=修改某个变量的内容,我们知道在其它语言中=是赋值符号,在这里也是差不多赋值的意思,例如 qqq=“qweqweq”,然后

echo $qqq ,就会输出qweqweq。

注意

  1. 等号两边不能接空格!!!

  2. 变量名只能有英文字母和数字且不能以数字开头

  3. 若有空格符可以使用双引号『 " 』或单引号『 ’ 』来将变量内容结合起来,但须要特别留意, 双引号内的特殊字符可以保有变量特性,但是单引号内的特殊字符则仅为一般字符;

    什么意思? 例如 我们定义qqq=" P A T H " , w w w = ′ PATH" , www=' PATH",www=PATH’,然后echo $qqq 和echo w w w 。 你 会 发 现 前 面 是 输 出 P A T H 变 量 的 内 容 而 后 面 是 输 出 www。你会发现前面是输出PATH变量的内容而后面是输出 wwwPATHPATH这几个字符

  4. 若该变量为扩增变量内容时,则需以双引号及 变 量 名 称 如 : 『 " 变量名称 如:『 " "PATH":/home』继续累加内容;

  5. 若该变量需要在其它子程序执行,则需要以 export 来使变量变成环境变量, 如『export PATH』;

  6. 取消变量的方法为:『unset 变量名称』。

自订变量转成环境变量: export

我们通过 less .bashrc查看家目录下的文件,可以看到一些exprot命令,这就是以当前用户登录bash时会导入的环境变量

变量键盘读取、数组与宣告:

  • read 例如read qqq就是等待用户从键盘输入作为qqq变量的内容

    -p 后面可以接提示字符

    -t 后面可以接等待的时间

    提示使用者 30 秒内输入自己的大名,将该输入字符串做成 named 变量

     read -p "Please keyin your name: " -t 30 named
     Please keyin your name: VBird Tsai
    
  • declare/typeset 宣告变量的属性

  • 数组属性array说明

    通过arr[0] = “123”;定义数组,通过echo ${arr[0]}取数组

命令别名设定: alias, unalias

登录讯息显示数据: /etc/issue, /etc/motd

还记得我们在终端机接口 (tty1 ~ tty6) 登入的时候,会有几行提示的字符串吗? 那个字符串写在哪里啊?呵呵!在 /etc/issue 里面啊!我们可以自己修改哦,试试修改看看吧。

issue 内的各代码意义
  • \d 本地端时间的日期;
  • \l 显示第几个终端机接口;
  • \m 显示硬件的等级 (i386/i486/i586/i686…);
  • \n 显示主机的网络名称;
  • \o 显示 domain name;
  • \r 操作系统的版本 (相当于 uname -r)
  • \t 显示本地端时间的时间;
  • \s 操作系统的名称;
  • \v 操作系统的版本。

还有个 /etc/issue.net 呢!这是啥?没啥啦!这个是提供给 telnet 这个远程登入程序用的。 当我们使用 telnet 连接到主机时,主机的登入画面就会显示 /etc/issue.net 而不是 /etc/issue 呢!

至于如果您想要让使用者登入后取得一些讯息,例如您想要让大家都知道的讯息, 那么可以将讯息加入 /etc/motd 里面去!

书上是这么说的,但是我在ubuntu18.04中并没有找到这个文件,上网查后发现想要自定义登入欢迎信息应该先进入/etc/update-motd.d目录。可以发现很多数字开头的文件。通过file命令查看可以发现都是shell script,也就是shell脚本。其实在我们登录的时候会按照前面数字从小到大的顺序执行这些script,所以我们可以自己创建一个文件,例如99-welcome,然后编辑文件如下

#!/bin/sh      
echo hello,welcome

上面第一行是固定格式,下面的echo我们都知道是输出内容,编辑完后 :wq!保存并退出,然后不要忘记更改文件权限了,要让他可执行。chmod 755 11-welcome。这时候再重写登录,你就能看到自定义的欢迎语了。

我按照上面的做法确实能显示欢迎语,但是我无法修改,反正就是达不到我想要的效果。

推荐一篇博客

  • sudo chmod -x /etc/update-motd.d/* 禁用所有的欢迎语

  • sudo apt install inxi screenfetch ansiweather 安装需要的软件

  • Create a new script

    创建01-custom的文件 代码如下:

    #!/bin/sh
    echo "GENERAL SYSTEM INFORMATION"
    /usr/bin/screenfetch
    echo
    echo "SYSTEM DISK USAGE"
    export TERM=xterm; inxi -D
    echo
    echo "CURRENT WEATHER AT THE LOCATION"
    # Show weather information. Change the city name to fit your location
    ansiweather -l bratislava
    
  • Make this script executable

    sudo chmod +x /etc/update-motd.d/01-custom
    

然后登录就可以看到一个炫酷的登陆界面了。但是我还是无法添加自己的欢迎语。。。很郁闷。用echo也不行,printf也不行。过了一会儿修改的内容又可以了,搞不懂啊,难道是没有同步?而且好像搞了这个花里胡哨的东西后连接变慢了。。。

我去,我还是卸载了吧。

终于可以显示自定义的欢迎语了,但是这黑底白字有点普通啊,调一下字体颜色。教程

环境设定档: bashrc, ~/.bashrc, ~/.profile, profile…,/etc/inputrc, source

要注意的是,在指令列输入的变量也好、命令别名也罢, 都是针对该次登入的设定而已,所以只要您一注销,那么上次的设定值就会不见去! 因此,我们需要有几个档案来帮助我们,每次登入的时候,就已经帮我们搞定了环境的设定啰!

  • 系统设定值

    所谓的系统设定值,也就是说每个使用者进入到 bash shell 之后,会先读取的设定档案! 预设的设定档案有下列几个:

    • /etc/sysconfig/i18n 。i18n是国际化的意思,18好像是中间省略了18个单词,Ubuntu似乎找不到这个文件

    • /etc/profile

      # /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
      # and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
      
      if [ "${PS1-}" ]; then
        if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
          # The file bash.bashrc already sets the default PS1.
          # PS1='\h:\w\$ '
          if [ -f /etc/bash.bashrc ]; then
            . /etc/bash.bashrc
          fi
        else
          if [ "`id -u`" -eq 0 ]; then
            PS1='# '
          else
            PS1='$ '
          fi
        fi
      fi
      
      if [ -d /etc/profile.d ]; then
        for i in /etc/profile.d/*.sh; do
          if [ -r $i ]; then
            . $i
          fi
        done
        unset i
      fi
      

      我们可以看到$和#,是不是这个提示符是在这里设置的呢?我们不妨修改一下啊,然后会发现提示符并没有改变,别忘了撤销你的修改哦!

    • /etc/bashrc

      这个档案在规划 umask 的功能,也同时规划出提示字符的内容 (就是里头那个 PS1 啦!) 。特别留意的是,这个档案在不同的 Linux distribution 里面,摆放的位置可能不太一样呢! 所以需要查询一下才行呦!

      通过locate bashrc寻找位置,然后打开文件我们可以发现有如下的语句

      if [ "$USER" = "root" ]; then
      	printf "%s" "#";
      else
      	printf "%s" "\$"
      fi
      

      难点这里可以修改提示符?我们不妨试试。发现也不行,记得还原改动哦!

    • /etc/profile.d/*.sh

      /etc/profile.d 是一个目录,里面针对 bash 及 C-shell 规范了一些数据。 你可以自行设定一些 *.sh 的文件名的档案来书写自己的系统设定值喔!

    • /etc/man.config

      在ubuntu下找不到这个文件

  • 个人设定值

    前面都是系统设定值,但是对于我们每一个用户都有自己的习惯与喜好,我们的个人设定值该怎么设置与存储呢?既然是用户自己的,那文件肯定位于用户的家目录下。我们在家目录下 ls -a就可以看到很多的个人设置值。

    .bash_history .cache .config .mysql_history .pip .ssh .viminfo .Xauthority
    .bashrc .cmake .dbus .gnupg .local .pearrc .pydistutils.cfg .sudo_as_admin_successful .vnc

    • ~/.bashrc

      我的个人化设定值都会写在这里

    • ~/.bash_profile, ~/.bash_login, ~/.profile

      ubuntu不在家目录下,使用 locate .bash_logout可以看到它的位置,不要忘记locate这条命令哦。

      这三个档案通常只要一个就够了(ubuntu下是.profile),一般预设是以 ~/.bash_profile 的檔名存在。 会有这么多的档案,其实是因应其它 shell 转换过来的使用者的习惯而已。 这个档案可以定义个人化的路径 (PATH) 与环境变量等等。不过,还是有顺位上的差异, bash 启动时,会先去读取 ~/.bash_profile,找不到时,就去读取 ~/.bash_login ,然后才是 ~/.profile。

    • ~/.bash_history

      顾名思义,bash的历史记录

    • ~/.bash_logout

      这个档案则记录了『当我注销 bash 后,系统再帮我做完什么动作后才离开』的意思。ubuntu不在家目录下,使用 locate .bash_logout可以看到它的位置,不要忘记locate这条命令哦。

在我们登录bash后这些设定文档是如何读取的呢?

  1. 先读取/etc/profile,再根据它的内容去读取其他的设定档
  2. 根据不同的使用者,到使用者家目录去读取 ~/.bash_profile 或 ~/.bash_login 或 ~/.profile 等设定档;
  3. 根据不同使用者,到他家目录去读取 ~/.bashrc

所以说,最终读取的才是最后的设定

书上是这么说的,但我感觉Ubuntu好像不是这个读取顺序,为什么这么说呢,我原来的.bashrc内容如下

#set oracle jdk environment\n
export JAVA_HOME=/usr/java/jdk\n
export JRE_HOME=\${JAVA_HOME}/jre  \n
export CLASSPATH=.:\${JAVA_HOME}/lib:\${JRE_HOME}/lib\n
export PATH=${JAVA_HOME}/bin:\${PATH}

export HISTTIMEFORMAT="%d/%m/%y %T "

export PROMPT_COMMAND="history -a; $PROMPT_COMMAND"

这个文件可能被我修改过,导致第5行$前面多了个\,所以PATH变量只有JAVA_HOME了,我们这时候使用source .bashrc加载资源,这时候任何命令包括ls都无法执行了,因为找不到路径。但是我们重新登录一下就又可以执行ls了,所以我猜测.bashrc并不是最后加载的。

而且我发现似乎这个文件并不会加载,每次需要我自己加载才会生效。而且好像连/etc/skel/.bashrc也不会自己加载,需要我手动加载后才会生效。我们查看/etc/profile发现确实没有加载的代码。

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

加载的是/etc/bash.bashrc和执行/etc/profile.d下的脚本。我们修改一下文件如下:(仿写的,好没学到脚本)

if [ "${PS1-}" ]; then
  if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
    # The file bash.bashrc already sets the default PS1.
    # PS1='\h:\w\$ '
    if [ -f /etc/bash.bashrc ]; then
      . /etc/bash.bashrc
    fi
    if [ -f /etc/skel/.bashrc ]; then
      . /etc/skel/.bashrc
    fi
    if [ -f /home/ubuntu/.bashrc ]; then
      . /home/ubuntu/.bashrc
    fi
  else
    if [ "`id -u`" -eq 0 ]; then
      PS1='# '
    else
      PS1='$ '
    fi
  fi
fi

if [ -d /etc/profile.d ]; then
  for i in /etc/profile.d/*.sh; do
    if [ -r $i ]; then
      . $i
    fi
  done
  unset i
fi

其实就是加了两个判断语句,如果文件存在,则加载。还有就是那个用户的配置文件我是写死的,只加载指定用户的配置文件,这肯定是不行的,我们应该有个循环,加载所有用户的配置文件,不过这都是后面的事情了。

万用字符与特殊符号

  • *:万用字符,代表 0 个或多个字符(或数字)
  • ?:万用字符,代表『一定有』一个字母
  • #:批注,这个最常被使用在 script 当中,视为注释!
  • :转义符
  • |:分割两个管线命令的界定
  • ;:连续性命令的界定(注意!与管线命令并不相同)
  • ~ : 使用者的家目录
  • $:亦即是变量之前需要加的变量取代值
  • &:将指令变成背景下工作
  • !:逻辑运算意义上的『非』 not 的意思!
  • /:路径分隔的符号
  • > , >> : 输出导向,分别是『取代』与『累加』
  • ’ : 单引号,不具有变量置换的功能
  • " : 具有变量置换的功能!
  • ``:两个『 ` 』中间为可以先执行的指令!也可以用$()取代
  • () : 在中间为子 shell 的起始与结束
  • [] :在中间为字符的组合
  • {} :在中间为命令区块的组合!
  • Ctrl + C 终止目前的命令
  • Ctrl + D 输入结束(EOF),例如邮件结束的时候;
  • Ctrl + M 就是 Enter 啦!
  • Ctrl + S 暂停屏幕的输出
  • Ctrl + Q 恢复屏幕的输出
  • Ctrl + U 在提示字符下,将整列命令删除
  • Ctrl + Z 『暂停』目前的命令

数据流重导向

> , >> ,表示将符号左边的导入符号右边,第一个符号是覆盖,第二个是追加

但是上面的两个符号只会重定向正确的输出,如果想要重定向错误的输出则需要 2> 。用法和上面一样哦。

那么那个 < 又是什么呀!?呵呵!以最简单的说法来说, 那就是『将原本需要由键盘输入的数据,经由档案来读入』的意思

命令执行的判断依据: ; , &&, ||

在某些时候,我们希望可以一次执行多个指令,例如关机时,希望我可以先执行两次 sync ,然后才 shutdown 计算机,那么可以怎么作呢?这样做呀sync; sync; shutdown -h now

在指令与指令中间利用分号 (😉 来隔开,这样一来,分号前的指令执行完后, 就会立刻接着执行后面的指令了。

如果有c语言基础的就会知道&&是强与,也就是如果前面不符合条件的话后面不会进行执行判断。在bash也是一样,如果我们需要在条件成立的情况下玩成某条指令的话可以把条件放前面,指令放后面。 || 也是一样的,如果前面满足了就不会执行后面的指令。

管线命令

管线命令使用 | 符号,使用管线命令的几条指令,左边指令的输出作为右边指令的输入。

撷取命令: cut, grep

  • cut : cut - remove sections from each line of files

    更多的信息可以使用man cut查看

  • grep : grep, egrep, fgrep, rgrep - print lines matching a pattern

    也就是从一行中找到我们需要的部分

双向重导向: tee

在前面我们讲了 > 可以将输出重导向到指定的文件中去,但是如果有时候我们既希望导入到文件,又希望能在屏幕上看到呢?这时候就要使用 tee命令了

tee - read from standard input and write to standard output and files

-a, --append

例如前面我们通过ls > output就可以将输出导入到output文件,此时屏幕上不会显示任何东西,而使用ls | tee output2可以将ls的内容同时输出到文件和屏幕。

查看变量:set,env

使用set命令可以查看所有的变量,使用env命令可以查看所有的环境变量。

取消变量:unset

取消 别名:unalias

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Little BigUs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值