【Linux命令行与Shell脚本编程】第五章 理解 Shell

news/2024/4/25 22:19:24/文章来源:https://blog.csdn.net/qq_44765647/article/details/130315056

Linux命令行与Shell脚本编程

第五章 理解 Shell


文章目录

  • Linux命令行与Shell脚本编程
    • 五,理解 Shell
      • 5.1,shell的类型
      • 5.2,shell的父子关系
        • 5.2.1,进程列表 ()
        • 5.2.2 子shell的用法
          • 1,后台模式
          • 2,后台进程列表
          • 3,协程
      • 5.3,外部命令和内建命令
        • 5.3.1,外部命令
        • 5.3.2,内建命令
          • 1,history 命令
          • 2,alias 命令别名


五,理解 Shell

学习shell进程及其在各种情况下的运作方式。探究如何创建子shell及其与父shell之间的关系,
了解各种会创建子进程和不会创建子进程的命令。
另外,本章还会涉及一些提高命令行效率的shell技术.

5.1,shell的类型

当登录系统时,系统启动的shell程序取决于个人用户配置。
在/etc/passwd文件中,用户记录的第7个字段中列出了该用户的默认shell程序。
只要用户登录某个虚拟控制台终端或是在GUI中启动终端仿真器,默认的shell程序就会启动。如用户 christine 使用 GNU bash shell作为自己的默认shell程序:$ cat /etc/passwdchristine:x:1001:1001::/home/christine:/bin/bash在现代Linux系统中,bash shell程序(bash)通常位于/usr/bin目录。
也有可能位于/bin目录。
which bash命令可以帮助找出 bash shell 的位置:$ which bash/usr/bin/bash
长列表中文件名尾部的星号(*)表明bash文件(bash shell)是一个可执行程序。$ 1s -1F /usr/bin/bash-rwxr-xr-x. 1 root root 1219248 Nov 8 11:30 /usr/bin/bash*
大多数Linux系统中, /etc/shells文件中列出了各种 已安装的shell,这些shell可以作为用户的默认shell。$ cat /etc/shells/bin/sh/bin/bash/usr/bin/sh/usr/bin/bash/bin/csh/bin/tesh/usr/bin/csh/usr/bin/tcsh/usr/bin/zsh/bin/zsh
用户可以将这些shell程序中的某一个作为自己的默认shell。
很少有人使用其他的shell作为默认的交互式shell。
默认的交互式shell(default interactiveshell)也称登录shell(loginshell),
只要用户登录某个虚拟控制台终端或是在GUI中启动终端仿真器,该shell就会启动。
作为默认的系统shell(default systemshell),sh(/bin/sh)用于那些需要在启动时使用的系统shell脚本。
某些发行版使用软链接将默认的系统shell指向bash shell,比如CentOS发行版:$ which sh/usr/bin/sh$ 1s -l /usr/bin/shlrwxrwxrwx. 1 root root 4 Nov 8 11:30 /usr/bin/sh -> bash
Ubuntu 默认链接到 dash可以启动任意一种已安装的shell,只需输入其名称即可。但屏幕上不会有任何提示或消息表明你当前使用的是哪种shell。
$0变量: 命令 echo$0 会显示当前shell的名称,提供必要的参考。使用echo$0显示当前所用shell的做法仅限在shell命令行中使用。如果在 shell脚本中使用,则显示的是该脚本的名称。输入命令dash,启动 Dash
shell,通过echo $0显示新的shell。$ echo $0- bash$ dash$ echo $0dash
- 表示是用户登录的shell

5.2,shell的父子关系

用户登录某个虚拟控制台终端或在GUI中运行终端仿真器得时所启动的默认的交互式 shel(登录shell)是一个父shell。
当在CLI提示符处输入bash命令(或是其他shell程序名)日时,会创建新的shell程序。这是一个子shell。子shell也拥有CLI提示符,同样会等待命令输入。$ ps -fUID          PID    PPID  C STIME TTY          TIME CMDroot         216       0  0 09:06 ?        00:00:00 /bin/sh -i -c /bin/bash || croot         217     216  0 09:06 ?        00:00:00 /bin/bashroot         250     217  0 09:09 ?        00:00:00 ps -f$ bash$ ps -fUID          PID    PPID  C STIME TTY          TIME CMDroot         216       0  0 09:06 ?        00:00:00 /bin/sh -i -c /bin/bash || croot         217     216  0 09:06 ?        00:00:00 /bin/bashroot         251     217  0 09:09 ?        00:00:00 bashroot         260     251  0 09:10 ?        00:00:00 ps -f输入命令bash之后,就创建了一个子shell。第二个ps-f是在子shell中执行的。
显示结果中看到有两个bash shell程序在运行。一个是父shell进程,其PID为 217。另一个是子shell进程,其PID为 251。子shell的 父进程ID(PPID) 是  217, 表明这个 217 进程就是该子shell的父进程。在生成子shell进程时,只有部分父进程的环境被复制到 子shell环境中。
子shell既可以从父shell中创建,也可以从另一个子shell中创建

bash命令行选项

选项描述
-c string从 string 中读取命令 并处理
-i启动一个能接收用户输入的交互式shell
-l作为登录shell 启动
-r启动一个受限shell,将用户限制在默认目录中
-s从标准输入中读取命令

5.2.1,进程列表 ()

命令列表:单行中可以指定要依次运行的一系列命令,以 ';' 分割,所有命令依次执行。$ pwd ; ls test* ; cd /etc ; pwd ; cd ; pwd ; ls my*/home/christinetest_file  test_one  test_two/etc/home/christinemy_file  my_scrapt  my_script  my_scrypt
进程列表:命令列表必须将命令放入圆括号内:$ (pwd ; ls test* ; cd /etc ; pwd ; cd ; pwd ; ls my*)/home/christinetest_file  test_one  test_two/etc/home/christinemy_file  my_scrapt  my_script  my_scrypt
圆括号的加入使 命令列表 变成了进程列表,生成了一个子shell来执行这些命令。
注意 进程列表是命令分组(commandgrouping)的一种。
另一种命令分组是将命令放入花括号内,并在命令列表尾部以分号(;)作结。语法为:{command;}。使用花括号进行命令分组并不会像创建子shell,是否生成了子shell,需要使用命令输出一个环境变量的值。
echo $BASH_SUBSHELL。如果该命令返回 0,那么表明没有子shell。如果该命令返回 1或者其他更大的数字,则表明存在子shell$ pwd ; echo $BASH_SUBSHELL/home/christine0$ (pwd ;  echo $BASH_SUBSHELL)/home/christine1
进程列表就是使用圆括号包起来的一组命令,能够创建子shell来执行这些命令。可以在进程列表中嵌套圆括号来创建子shell的子shell$ (pwd ; echo $BASH_SUBSHELL)/home/Christine1$ (pwd ; (echo $BASH_SUBSHELL))/home/Christine2
子shell在shell脚本中经常用于多进程处理。但创建子shell 要消耗更多的资源(比如内存和处理能力),会明显拖慢任务进度。在交互式CLI shell会话中,并非真正的多进程处理,原因在于终端与子shell的I/O绑定在了一起。

5.2.2 子shell的用法

进程列表、协程和管道都用到了子shell,各自都可以有效运用于交互式shell。
在交互式shell中,一种高效的子shell用法是后台模式
1,后台模式
在后台模式中运行命令可以在处理命令的同时让出CLI,以供他用。借助sleep 演示后台模式。sleep 命令会接受一个参数作为希望进程等待(睡眠)的秒数。该命令在shell脚本中常用于引入一段暂停时间,然后返回shell CLI提示符:
将命令置入后台模式,可以在命令末尾加上字符 &。$ sleep 10&[1] 338$ ps -fUID          PID    PPID  C STIME TTY          TIME CMDroot         314       0  0 09:38 ?        00:00:00 /bin/sh -i -c /bin/bash || croot         315     314  0 09:38 ?        00:00:00 /bin/bashroot         338     315  0 09:41 ?        00:00:00 sleep 10root         339     315  0 09:41 ?        00:00:00 ps -fsleep命令会在后台(&)睡眠 10秒。
当其被置入后台时,在shell CLI提示符返回之前,屏幕上会出现两条信息。第一条信息是方括号中的后台作业号(1)。第二条信息是后台作业的进程ID(2542)
可以使用jobs命令来显示后台作业信息。jobs命令能够显示当前运行在后台模式中属于你的所有进程(作业)$ jobs[1]+  Running                 sleep 10 &-l(小写字母l)选项,还可以看到更多的相关信息。显示命令的PID.$ jobs -l[1]+  338 Running                 sleep 10 &
在jobs命令的显示中,最近启动的进程在进程号后会有加号(+),之前启动的进程以减号(-)表示。
已完成的 Done$ jobs[1]-  Running                 sleep 1000 &[2]+  Done                    sleep 3
2,后台进程列表
通过将进程列表置入后台,可以在子shell中进行大量的多进程处理。好处: 终端不再和子shell的I/O绑定在一起。
进程列表是子shell中运行的一系列命令。在进程列表中加入sleep命令并显示BASH_SUBSHELL变量,结果不出所料:$ (sleep 2 ; echo $BASH_SUBSHELL ; sleep 2)&[2] 2553$ 1[2]+  Done                   ( sleep 2; echo $BASH_SUBSHELL; sleep 2 )使用 tar 命令创建备份文件是有效利用后台进程列表的一个更实用的例子:$ (tar -cf Doc.tar Documents ; tar -cf Music.tar Music)&[1] 2567$ ls *.tarDoc.tar Music.tar[1]+ Done                     ( tar -cf Doc.tar Documents;tar -cf Music.tar Music )
将进程列表置入后台并不是子shell在CLI中仅有的创造性用法,还有一种方法是协程。
3,协程
协程同时做两件事:一是在后台生成一个子shell,二是在该子shell中执行命令。
要进行协程处理,可以结合使用 coproc 命令以及 要在子shell中执行的命令:$ coproc sleep 10[1] 2689$ jobs[1]+  Running                  coproc COPROC sleep 10 &
在子shell中执行的后台命令是 coproc COPROC sleep 10。
COPROC 是 coproc命令给进程起的名字。
为协程命名:$ coproc My_Job { sleep 10; }[1] 2706$ jobs[1]+ Running                   coproc My_Job { sleep 10; } &必须确保在 { 和内部命令名之间有一个空格。内部命令以 ; 结尾。分号和 } 之间也得有一个空格.
只有在拥有多个协程时(进行通信)才需要对协程进行命名,否则的话,使用默认名称COPROC即可.
将协程与进程列表结合起来创建嵌套子shell$ coproc ( sleep 10; sleep 2 )[1] 2750$ jobs[1]+  Running                  coproc COPROC ( sleep 10; sleep 2 ) &$ ps --forestPID  TTY      TIME     CMD2367 pts/0    00:00:00 bash2750 pts/0    00:00:00  \_ bash2751 pts/0    00:00:00  |   \_ sleep2752 pts/0    00:00:00  \_ ps

5.3,外部命令和内建命令

5.3.1,外部命令

外部命令(文件系统命令)是存在于bash shell之外的程序。并不属于shell程序的一部分。
外部命令程序通常位于/bin、/usr/bin、/sbin或 /usr/sbin目录中。
使用which命令和type命令找到其对应的文件名:(which命令只显示外部命令文件)$ which ps/usr/bin/ps$ type psps is /usr/bin/ps$ ls -l /usr/bin/ps-rwxr-xr-x. 1 root root 142216 May 11  2019 /usr/bin/ps
当执行外部命令时,就会创建一个子进程。这种操作称为衍生(forking)。
外部命令会显示其父进程以及自己所对应的衍生子进程:$ ps -fUID        PID  PPID  C STIME TTY          TIME CMDchristi+  2367  2363  0 10:47 pts/0    00:00:00 -bashchristi+  4242  2367  0 13:48 pts/0    00:00:00 ps -f
只要涉及进程衍生,就需要耗费时间和资源来设置新子进程的环境。因此,外部命令系统开销较高。
无论是衍生出子进程还是创建了子shell,都可以通过发送信号与其互通.

5.3.2,内建命令

内建命令无须使用子进程来执行。内建命令 和 shell编译成一体,作为shell的组成部分存在,无须借助外部程序文件来执行。$ type cdcd is a shell builtin$ type exitexit is a shell builtin
内建命令既不需要通过衍生出子进程来执行,也不用打开程序文件,所以执行速度更快,效率也更高有些命令有多种实现。例如,echo 和 pwd既有内建命令也有外部命令。两种实现略有差异。
查看命令的不同实现,可以使用type命令的 -a选项$ type echoecho is a shell builtin$ type -a echoecho is a shell builtinecho is /usr/bin/echoecho is /bin/echoecho is /usr/bin/echoecho is /bin/echo对于有多种实现的命令,如果想使用其外部命令实现,直接指明对应的文件即可。
使用外部命令 pwd,可以输入/usr/bin/pwd。
1,history 命令
bash shell会跟踪你最近使用过的命令。可以重新唤回这些命令,甚至加以重用。
history是一个实用的内建命令,能帮助你管理先前执行过的命令。
历史记录中通常保存最近的1000条命令(以设置保存在bash历史记录中的命令数量。为此,需要修改名为 HISTSIZE 的环境变量)$ history1  ps -f2  pwd
命令历史记录被保存在位于用户主目录的隐藏文件.bash_history之中:
在CLI会话期间,bash命令的历史记录被保存在内存中。当shell退出时才被写入历史文件!
使用 history命令的 -a选项 在不退出shell的情况下强制将命令历史记录写入.bash_history文件。
history命令的输出与.bash_history文件内容一样,除了最近的那条history命令.如果打开了多个终端会话,则仍然可以使用 history -a命令在每个打开的会话中向 .bash_history文件添加记录。但是历史记录并不会在其他打开的终端会话中自动更新。因为.bash_history文件只在首次启动终端会话的时候才会被读取。要想强制重新读取.bash_history文件,更新内存中的终端会话历史记录,可以使用history -n命令唤回:唤回并重用历史列表中最近的命令。输入 !!,然后按Enter键,唤回并重用最近那条命令输入 !! 时,bash会先显示从shell的历史记录中唤回的命令,然后再执行该命令。$ echo 11$ !!echo 11可以唤回历史记录中的任意命令。输入 ! 和命令在历史记录中的编号:$ history1  ps -f2  pwd$ !2pwd/home/christine清除:输入history -c 清除。接下来再输入history -a,刷新清除 .bash_history文件。
2,alias 命令别名
命令别名允许为常用命令及其参数创建另一个名称,从而将输入量减少到最低。
Linux发行版很有可能已经为你设置好了一些常用命令的别名。查看当前可用的别名 使用alias命令以及选项 -p可以$ alias -palias 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 li='ls -i$ li34665652 Desktop          1415018 NetworkManager.conf1414976 Doc.tar         50350618 OldDocuments
命令别名属于内建命令,所以别名仅在其被定义的 shell进程中才有效.$ alias li='ls -i'$ bash$ libash: li: command not found...删除指定的别名 输入 unalias alias-name。
如果被删除的别名不是你设置的,那么等下次重新登录系统的时候,该别名就会再次出现。可以通过修改环境文件永久地删除某个别名。
让别名在不同的子shell中都奏效. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_102577.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何评估小程序开发费用:从项目规模到技术需求

作为一种越来越受欢迎的移动应用,小程序的开发费用是许多企业和个人考虑的重要因素之一。但是,要确定小程序开发费用并不是一件容易的事情,因为它涉及到多个因素,从项目规模到技术需求。 项目规模 小程序开发的费用通常与项目规…

Linux部署人大金仓(Kingbase8)

陈老老老板🦸 👨‍💻本文专栏:国产数据库-人大金仓(kingbase8)(主要讲一些人大金仓数据库相关的内容) 👨‍💻本文简述:本文讲一下LInux上部署人大…

Vue+Echarts 项目演练(中)后台数据接口的创建

全局引用Echarts与axios 后台接口创建express路由 api接口数据创建 全局引用Echarts与axios vue3.0的挂载方式&#xff1a;使用Provide/Inject依赖注入&#xff0c;将替代vue2中在原型链上挂载一些属性在app.vue中使用provider来给后代们提供数据 <script> import { p…

经典数据结构之2-3树

2-3树定义 2-3树&#xff0c;是最简单的B-树&#xff0c;其中2、3主要体现在每个非叶子节点都有2个或3个子节点&#xff0c;B-树即是平衡树&#xff0c;平衡树是为了解决不平衡树查询效率问题&#xff0c;常见的二叉平衡书有AVL树&#xff0c;它虽然提高了查询效率&#xff0c…

深入JVM了解Java对象实例化过程

文章目录 一、对象创建方式二、对象产生步骤1、判断对象是否已经加载、链接、初始化2、为对象分配内存空间3、处理并发问题3.1 TLAB 4、初始化零值5、完善对象内存布局的信息6、调用对象的实例化方法 <init>7、总结 三、对象的内存布局1、对象头1.1 运行时元数据&#xf…

详解树与二叉树的概念,结构,及实现(上篇)

目录 一&#xff0c; 树 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 二&#xff0c; 二叉树 2.1二叉树概念 三&#xff0c;特殊的二叉树 1. 满二叉树 2. 完全二叉树 3. 1 二叉树的性质 3. 2 二叉树的存储…

【速卖通】 AliExpress(速卖通)关键词搜索结果采集

采集场景 在AliExpress(速卖通) 首页中 http://www.aliexpress.com 中输入关键词&#xff0c;采集关键词搜索后得到的商品列表信息。 采集字段 关键词、标题、商品id、商品图片地址、商品详情链接、价格、免费退送货、星级、已出售数量、店铺名 采集结果 采集结果可导出为E…

Linux-初学者系列——篇幅7_文本编辑和处理命令

文本编辑和处理命令-目录 一、系统基本编辑命令安装vim软件工具包语法格式&#xff1a; 1、vim编辑命令模式01 普通模式02 编辑模式03 命令模式 2、编辑文件技巧01 批量删除多行指定信息02 批量增加多列指定信息03 编辑常见问题错误1&#xff1a;没有指定编辑信息错误2&#xf…

基于TensorRT的yolov5 实例分割部署

yolov5-7.0 github: https://github.com/ultralytics/yolov5/tree/master 1. 代码的使用 1.1 训练yolov5-seg模型 使用的yolov5-7.0的代码,github下载:https://github.com/ultralytics/yolov5/releases/tag/v7.0 训练指令 python segment/train.py --data coco128-seg.y…

centos7 查看服务器配置信息

1.linux查看版本当前操作系统发行信息 cat /etc/centos-release cat /etc/centos-release 2、查看内核版本uname -a或者cat /proc/version 3、查看CPU参数 1&#xff09;、查看 CPU 物理个数   grep physical id /proc/cpuinfo | sort -u | wc -l 2&#xff09;、查看 CPU …

SpringCloud:ElasticSearch之DSL查询文档

elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;一般测试用。例如…

magento webapi 接口返回 json对象

前言 现在主流的项目开发都是前后端分离&#xff0c;数据通过json对象格式进行传输。但是magento框架&#xff0c;和传统PHP框架相比&#xff0c;区别很大。虽然也支持以RestApi的形式传输数据&#xff0c;但是要么格式并非是传统jsonObject要么就是需要大量的get、set方法。本…

关于xilinx使用PCIE实现FPGA的部分重配置实现(MCAP)

平台&#xff1a;vivado21018.3 芯片&#xff1a;xcku115-flva1517-2-i (active) 本文官方文档&#xff1a;Xilinx_Answer_64761_Ultrascale_Devices 本文驱动下载地址&#xff1a;64761 - Bitstream Loading across the PCI Express Link in UltraScale and UltraScale Dev…

JAVA——线程池

目录 一、线程池的概念 二、Java标准库中的线程池 三、ThreadPoolExecutor 类的参数 四、线程池的拒绝策略 五、模拟实现线程池 一、线程池的概念 线程池顾名思义就是集中存储线程的地方——联想一下水池。 线程池是一种多线程处理形式&#xff0c;处理过程中将任务添加到…

Ext4日志优化-iJournaling

背景 这几年随着SSD等高性能介质的普及&#xff0c;及其在大规模分布式存储系统上的应用。基于Append only的日志写入技术也应用得越来越多&#xff0c;这几天刚好有空&#xff0c;重读了Ext4文件系统的日志部分的内容&#xff0c;也正好看到一篇对Ext4日志技术进行优化的论文…

《编码——隐藏在计算机软硬件背后的语言》精炼——第11章(门)

“The only source of knowledge is experience.” - Albert Einstein 引言 编码是一种处理并表达信息的方式&#xff0c;它包括摩斯电码、盲文、二进制语言等等&#xff0c;当然作为计算机类的经典书籍&#xff0c;这本书简述了计算机中以二进制数为基础的编码方式&#xff0…

nginx简单介绍

文章目录 1. 下载并解压2. 80端口被占用&#xff0c;更改nginx默认的监听端口3. 访问nginx4. 在linux上安装nginx5. nginx常用命令6. nginx.conf 1. 下载并解压 官网下载 2. 80端口被占用&#xff0c;更改nginx默认的监听端口 更改conf/nginx.conf文件 3. 访问nginx ht…

【Linux】popen pclose接口介绍

本篇文章简单讲述了c语言接口popen/pclose的用法 1.函数作用 函数定义如下 #include <stdio.h>FILE *popen(const char *command, const char *type); int pclose(FILE *stream);1.1 popen popen函数会创建一个管道&#xff0c;fork后调用shell来打开进程。由于管道的…

射频封装技术:层压基板和无源器件集成

射频和无线产品领域可以使用非常广泛的封装载体技术&#xff0c;它们包括引线框架、层压基板、低温共烧陶瓷&#xff08;LTCC&#xff09;和硅底板载体&#xff08;Si Backplane&#xff09;。由于不断增加的功能对集成度有了更高要求&#xff0c;市场对系统级封装方法&#xf…

Qt 项目Mingw编译器转换为VS编译器时的错误及解决办法

错误 在mingw生成的项目&#xff0c;转换为VS编译器时通常会报些以下错误&#xff08;C4819警告&#xff0c;C2001错误&#xff0c;C2143错误&#xff09; 原因及解决方式 这一般是由于字符编码引起的&#xff0c;在源代码文件中包含了中文字符导致的。Qt Creator 生成的代码文…