bash shell命令学习之理解shell(存在疑问)

本文详细介绍了Linux bash shell的基础知识,包括shell的类型、父子关系,特别是子shell的创建与退出。通过示例展示了进程列表(存在疑问)的用法,解释了如何在后台模式下运行命令以及使用协程命令coproc。同时,讨论了shell的内建命令与外部命令的区别,并提到了history和alias这两个实用功能。

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

本博客内容来自《Linux命令行与shell脚本编程大全》第五章以及第一章、第二章等部分节选

目录

1、背景

2、shell的类型

3、shell的父子关系

进程列表

命令列表

进程列表(存在疑问)

子shell新奇用法

后台模式

在后台使用进程列表

协程命令coproc

4、shell的内建命令

外部命令

内建命令

history命令

命令别名alias


1、背景

Linux系统分为以下四部分

Linux内核

GNU工具

图形化桌面环境

应用软件

其中GNU工具是由GNU组织(GNU's Not Unix)开发的一套完整的Unix工具,该工具内有一种特殊的交互式工具——shell,为用户提供启动程序、管理文件系统中的文件以及Linux系统上进程的途径,其核心是命令行提示符。所有Linux发行版的shell都是bash shell,这是GNU项目提供的默认版本。

shell提供了文本命令行界面(command line interface,CLI),CLI只接受文本输入,也只能显示出文本和基本的图形输出。

当然,shell不仅仅是一种CLI,而是一个时刻都在运行的复杂交互式程序。

2、shell的类型

系统启动后使用的shell类型可以在/etc/passwd文件中查看,第七个字段即为默认shell程序

[root@izwz9194nuv8g0cwqfqsh3z ~]# cat -n /etc/passwd
     1    root:x:0:0:root:/root:/bin/bash

此外,还有一个默认shell是/bin/sh,这个shell主要用于需要在启动时使用的系统shell脚本

[root@izwz9194nuv8g0cwqfqsh3z ~]# ls -lF /bin/bash
-rwxr-xr-x 1 root root 960472 Dec  7  2016 /bin/bash*
[root@izwz9194nuv8g0cwqfqsh3z ~]# ls -lF /bin/sh
lrwxrwxrwx 1 root root 4 Aug 18  2017 /bin/sh -> bash*

可以看出在本文所选环境中,/bin/sh通过软链接设置为bash shell

3、shell的父子关系

父shell:用于登录某个虚拟控制器终端或在GUI中运行终端仿真器时所启动的默认交互shell

子shell:在CLI提示符后输入/bin/bash命令或其他等效bash命令时创建的新的shell程序,创建子shell是有代价的

[root@izwz9194nuv8g0cwqfqsh3z ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15419 15417  0 14:07 pts/0    00:00:00 -bash
root     15455 15419  0 14:25 pts/0    00:00:00 ps -f
[root@izwz9194nuv8g0cwqfqsh3z ~]# bash
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15419 15417  0 14:07 pts/0    00:00:00 -bash
root     15456 15419  0 14:25 pts/0    00:00:00 bash
root     15467 15456  0 14:25 pts/0    00:00:00 ps -f

上述显示表明第二个ps -f命令是在子shell中运行的,可以用ps --forest查看父子关系

[root@izwz9194nuv8g0cwqfqsh3z ~]# ps --forest
  PID TTY          TIME CMD
15419 pts/0    00:00:00 bash
15456 pts/0    00:00:00  \_ bash
15474 pts/0    00:00:00      \_ ps

退出子shell采用exit命令

进程列表

  • 命令列表

命令列表是将一连串命令用 ; 分号隔开,如下所示,命令依次执行不存在任何问题

[root@izwz9194nuv8g0cwqfqsh3z ~]# pwd; ls; cd tast/; pwd; cd ..; ls
/root
file1  link  link_he  mod_test  tast
/root/tast
file1  link  link_he  mod_test  tast

  • 进程列表(存在疑问)

进程列表是在命令列表的基础上增加括号,如下所示,且进程列表执行后会创建子shell

[root@izwz9194nuv8g0cwqfqsh3z ~]# (pwd; ls; cd tast/; pwd; cd ..; ls)
/root
file1  link  link_he  mod_test  tast
/root/tast
file1  link  link_he  mod_test  tast
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps --forest
  PID TTY          TIME CMD
15419 pts/0    00:00:00 bash
15456 pts/0    00:00:00  \_ bash
15496 pts/0    00:00:00      \_ ps

此时进程处于子shell中,然后我发现一个书本上没有提到的很好玩的地方,先输入exit退出子shell,然后执行以下命令

[root@izwz9194nuv8g0cwqfqsh3z ~]# (ps --forest;pwd; ls; cd tast/; pwd; cd ..; ls)
  PID TTY          TIME CMD
15419 pts/0    00:00:00 bash
15497 pts/0    00:00:00  \_ bash
15498 pts/0    00:00:00      \_ ps
/root
file1  link  link_he  mod_test  tast
/root/tast
file1  link  link_he  mod_test  tast
[root@izwz9194nuv8g0cwqfqsh3z ~]# exit
logout
Connection closing...Socket close.

在这里就存在疑问了,按道理我输入exit会退出子shell,但是没有,直接退出系统了,说明我在进程列表开头增加的ps --forest命令虽然是在子shell中执行的,但是执行完之后自动退出了子shell,原因是什么呢?希望知道的朋友留言告诉我一声~

子shell新奇用法

进程列表、协程和管道(后面介绍)都利用了shell

  • 后台模式

在后台模式中运行命令可以在处理命令的同时让出CLI,以供他用。可以使&进入后台模式,以sleep为例,如下所示

[root@izwz9194nuv8g0cwqfqsh3z ~]# sleep 10&
[1] 15561
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15506 15504  0 14:45 pts/0    00:00:00 -bash
root     15561 15506  0 15:05 pts/0    00:00:00 sleep 10
root     15562 15506  0 15:05 pts/0    00:00:00 ps -f
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
root     15506 15504  0 14:45 pts/0    00:00:00 -bash
root     15563 15506  0 15:05 pts/0    00:00:00 ps -f
[1]+  Done                    sleep 10


其中,&符号是进入后台的参数,此外,可以通过jobs命令查看正在后台运行的作业,也可以添加 -l 参数显示更多

[root@izwz9194nuv8g0cwqfqsh3z ~]# jobs
[1]+  Running                 sleep 10 &

  • 在后台使用进程列表

要是想在子shell中进行繁重的处理工作,又不想让子shell的I/O受制于终端,可以将进程列表置入后台模式,操作如下

[root@izwz9194nuv8g0cwqfqsh3z ~]# (sleep 2; echo "doing jobs"; sleep 2)&
[1] 15574
[root@izwz9194nuv8g0cwqfqsh3z ~]# doing jobs

[1]+  Done                    ( sleep 2; echo "doing jobs"; sleep 2 )

使用sleep和echo命令的进程列表只是作为一个示例,其实更具有实用意义的命令是tar进行文件归档以上一篇博客中的例子:

#(tar -cvf test.tar test/ test2/)&

这样可以避免在归档大文件时阻塞CLI的情况发生

  • 协程命令coproc

协程可以同时做两件事情,在后台生成子shell,并在子shell中执行命令。基本用法如下:

[root@izwz9194nuv8g0cwqfqsh3z ~]# coproc sleep 10
[1] 15586
[root@izwz9194nuv8g0cwqfqsh3z ~]# jobs
[1]+  Running                 coproc COPROC sleep 10 &

其中,COPROC是协程给进程起的名字,存在多个协程时可以自己设置该名字,如下所示

[root@izwz9194nuv8g0cwqfqsh3z ~]# coproc My_Job { sleep 10; }
[1] 15596
[root@izwz9194nuv8g0cwqfqsh3z ~]# jobs
[1]+  Running                 coproc My_Job { sleep 10; } &

注意My_Job与{之间需要空格

使用协程也可以达到在后台使用进程列表的作用

[root@izwz9194nuv8g0cwqfqsh3z ~]# coproc (sleep 2; echo "doing jobs"; sleep 10)
[1] 15643
[root@izwz9194nuv8g0cwqfqsh3z ~]# jobs
[1]+  Running                 coproc COPROC ( sleep 2; echo "doing jobs"; sleep 10 ) &
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps --forest
  PID TTY          TIME CMD
15610 pts/0    00:00:00 bash
15643 pts/0    00:00:00  \_ bash
15645 pts/0    00:00:00  |   \_ sleep
15646 pts/0    00:00:00  \_ ps
[root@izwz9194nuv8g0cwqfqsh3z ~]# ps --forest
  PID TTY          TIME CMD
15610 pts/0    00:00:00 bash
15647 pts/0    00:00:00  \_ ps
[1]+  Done                    coproc COPROC ( sleep 2; echo "doing jobs"; sleep 10 )

可以看到,任务在后台执行,且创建了子shell;不过对于用户来说并没有进入子shell,还能愉快的操作父shell,真正实现了任务在后台执行的效果

4、shell的内建命令

外部命令

外部命令又称为文件系统命令,即存在于bash shell之外的程序,通常位于/bin、/usr/bin、/sbin或/usr/sbin中

ps就是一个外部命令,可以用which或type命令找到它

[root@izwz9194nuv8g0cwqfqsh3z ~]# which ps
/usr/bin/ps
[root@izwz9194nuv8g0cwqfqsh3z ~]# type -a ps
ps is /usr/bin/ps

外部命令执行时创建子进程的操作称为衍生,父进程发出外部命令ps -f,衍生出子进程来执行外部命令ps -f。

内建命令

内建命令与外部命令的区别在于不需要创建子进程来执行。如cd和exit等命令都是内建命令,用type可以知道命令的类型,用which只能显示外部命令文件,echo、pwd等既有内建命令又有外部命令,使用type -a可以查看不同实现。

[root@izwz9194nuv8g0cwqfqsh3z ~]# type cd 
cd is a shell builtin
[root@izwz9194nuv8g0cwqfqsh3z ~]# type ps
ps is hashed (/usr/bin/ps)
内建命令执行速度更快

[root@izwz9194nuv8g0cwqfqsh3z ~]# type -a echo
echo is a shell builtin
echo is /usr/bin/echo

想使用echo的外部命令实现,指明对应文件即可 /usr/bin/echo,如

[root@izwz9194nuv8g0cwqfqsh3z ~]# /usr/bin/echo hahha
hahha

  • history命令

history命令是很有用的,可以跟踪你用过的命令,以便唤回并重新使用。默认显示近期输入的1000条命令,如果想要改变这个值的大小,直接为环境变量HISTSIZE赋值,如:HISTSIZE=2000;

[root@izwz9194nuv8g0cwqfqsh3z ~]# history 
    1  ll
    2  ls
    3  cd /etc/passwd
    4  vim
    5  vim /etc/passwd
    6  man xterm
    7  man .man -help
    8  man -help
......(此处省略近千条)

如果想重新使用第N条,则执行 !N 即可,例如

......

  226  history 
  227  ps --forest
  228  history 
[root@izwz9194nuv8g0cwqfqsh3z ~]# !227
ps --forest
  PID TTY          TIME CMD
15610 pts/0    00:00:00 bash
17664 pts/0    00:00:00  \_ ps

如果只想唤回最近的命令,可以输入!!,例如

[root@izwz9194nuv8g0cwqfqsh3z ~]# /usr/bin/echo hahha
hahha
[root@izwz9194nuv8g0cwqfqsh3z ~]# !!
/usr/bin/echo hahha
hahha

历史命令被存储在隐藏文件.bash_history中,位于用户主目录,如下所示

[root@izwz9194nuv8g0cwqfqsh3z ~]# cat .bash_history 
ll
ls
cd /etc/passwd
vim
vim /etc/passwd
man xterm
man .man -help
man -help
man man
......

历史命令记录一开始是保存在内存的,如果要强制将其同步至文件,可以执行 history -a

当然,还有一种广为使用的命令搜索方法:

ctrl+r搜索:

在提示符后面,输入,要搜索的关键字:

(reverse-i-search)`':sed

就会自动联想出包含此关键字的历史命令

  • 命令别名alias

alias是内建命令,允许为常用命令(及其参数)创建别名,减少输入量

系统已有的别名可以通过命令 alias -p查看

[root@izwz9194nuv8g0cwqfqsh3z ~]# alias -p
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

注意:alias ls='ls --color=auto'表明终端支持彩色模式的列表

alias使用格式即

alias 别名=‘具体的命令组成’

当然,你所起的别名只在当前shell进程中有效(可以让其在子shell中也生效,见下一篇博客)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值