【Linux后端服务器开发】Shell外壳——命令行解释器
目录
一、Shell外壳概述
二、描述Shell外壳原理的生动例子
三、C语言模拟实现Shell外壳
一、Shell外壳概述
在狭义上 , 我们称Linux操作系统的内核为 Linux
在广义上 , Linux发行版 == Linux内核 + 外壳程序
就比如市面上现在的redhat, centos, ubuntu等等我们耳熟能详的Linux发行版,事实上这些Linux发行版都是基于Linux操作系统的内核,然后对之加装了不同的Shell外壳 ,最终做出不同种类的Linux发行版。

我们作为用户,是不能直接去操作Linux内核的,为什么呢?
- 直接去操作Linxu内核成本是极高的,学习成本、操作成本都不低
- 用户直接操作Linux内核存在风险,所以Linux内核对用户设置了权限限制
所以我们有了shell外壳程序来间接帮助我们操作Linux内核。
windows操作系统的Shell外壳是一个窗口图形界面,所以我们可以通过这个窗口图形,接收来自用户的点击、拖拽等操作,从而使用windows的各个功能。
Linux操作系统的Shell外壳的名字叫bash,所以我们也可以通过bash来传达我们的操作,即用户对bash输入指令,从而使用Linux操作系统的功能。
简单的说,Shell外壳程序是对Linux内核的一层封装 , 架起了用户和Linux沟通的桥梁。
命令行解释器
在大多数Linux发行版本中,是没有图形化界面的,那么,Shell是如何帮助用户和Linux内核进行沟通的呢?答案是命令行解释器,也就是小黑框。命令行解释器就是Shell外壳在Linux系统中的具体表现。
命令行解释器上每一行都有输入指令的提示,用户输入指令和选项之后,Shell外壳接收并解析该指令,然后发送给Linux内核去处理执行,Linux内核处理之后将结果反馈给Shell外壳,Shell外壳将结果解析返还给用户。
二、描述Shell外壳原理的生动例子
从前有座山,山里有座村,村里有个老村长,而你是村长的儿子——王二狗。同时你们村还有个远近闻名的媒婆——王婆,在你们当地有非常不错的口碑,曾撮合成功了无数对男女。
你作为村长的儿子,也老大不小了,也到了该找对象的年纪。你作为一个纯情的男人,心理自然还想着你们村的如花姑娘。
但是你还是一个害羞的小男生,不方便也不敢直接去和如花姑娘直说,所以你就只得找王婆来代为传递你的信息。
这天,你找到了王婆,说你想找如花姑娘相亲,王婆说可以帮你办这件事,然后她就把你想找如花姑娘约会这件事告诉了如花姑娘。如花姑娘说不行,她说她并不认识王二狗,不想和他相亲。于是王婆就很直白的告诉你说,如花姑娘压根不想和你相亲,你还是放弃吧。
所以王婆便是沟通你和如花姑娘的桥梁,类比用户和操作系统内核之间的媒介作用。

你心想,作为一个纯情的男人,我是不会放弃的!所以这天你有找到王婆,说再帮我问问看吧,我真的很喜欢如花姑娘[大哭]。
王婆说好吧,那我再给你传达最后一次,不过不出所料,结局再次上演,如花再次拒绝,王婆又把这个残忍的事实传达给你。
这时你还是放不下,有跟王婆说能不能再再帮我问一次。王婆此时直接拒绝了,说不要再这样子了,这样如花姑娘会不堪其扰内心厌烦且痛苦的(王婆顾及如花姑娘的感受,事实上也是在保护如花姑娘,防止你亲自去找她,做出极端的事情)。
所以王婆拥有拒绝传达信息的权利,类比Shell外壳可以拒绝一些非法的请求,从而保护os。

不过故事仍然没有结束,你可是村长的儿子啊,你的一再要求,王婆肯定会考虑到村长的面子。但是王婆也得考虑到自己的口碑,不能因为这件事把招牌给砸了,毕竟还忙着给其他男女说媒呢。
所以这时王婆想到一个绝妙的对策,招一个实习生来办这件事(王婆:让我的实习生来给你办这件事吧,我溜了哦~)。
实习生办这件事,对王婆来说有两个好处,一是王婆可以跟村长交代这件事她一直在办着,只不是是她的实习生在负责,二是就算实习生办砸了这件事也没关系,反正只要不是她王婆办的,这个招牌就不会砸。
王婆可以找实习生执行难度大的任务,类比Shell外壳可以创建子进程去执行有风险的任务,从而不影响Shell外壳。

总结
Shell外壳是对Linux内核的封装,连接沟通了用户(需求)与Linux内核(执行),这降低了用户的操作学习成本。
Shell外壳可以传达用户指令,交给操作系统内核去执行,最终把执行结果反馈给用户。
同时Shell外壳也可以直接拒绝用户,从而保护操作系统内核。
Shell外壳也可以通过创建Shell外壳程序的子进程的方式,来执行有风险的指令,从而来保护bash即Shell外壳本身。
三、C语言模拟实现Shell外壳
命令行解释器:
- 输出提示
- 获取用户输入
- 执行命令
核心算法:字符串切割、进程替换、环境变量调用、重定向
源代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>#define NUM 1024
#define OPT_NUM 64#define NONE_REDIR 0
#define INPUT_REDIR 1
#define OUTPUT_REDIR 2
#define APPEND_REDIR 3char commandLine[NUM];
char* myArgv[OPT_NUM];
int lastCode = 0;
int lastSig = 0;int redirType = NONE_REDIR;
char* redirFile = NULL;// 跳过空格
void skip_space(char* start)
{while (isspace(*start)){++start;}
}// 检查命令行是否是输入输出重定向
void command_check(char* commands)
{assert(commands);char* start = commands;char* end = commands + strlen(commands);while (start < end){if (*start == '>'){*start = 0;++start;if (*start == '>'){// 追加输出重定向// "ls -a -l >> test.txt"redirType = APPEND_REDIR;++start;}else{// 覆盖输出重定向// "ls -a -l > test.txt"redirType = OUTPUT_REDIR;}skip_space(start);redirFile = start;break;}else if (*start == '<'){// 输入重定向// "cat < test.txt"*start = 0;++start;skip_space(start);redirType = INPUT_REDIR;redirFile = start;break;}else {++start;}}
}int main()
{while (1){redirType = NONE_REDIR;redirFile = NULL;// 输入提示符char* pwd = getenv("PWD");char* token = strtok(pwd, "/");char* dir = token;while (token != NULL){dir = token;token = strtok(NULL, "/");}char* user = getenv("USER");if (strcmp(user, "root") == 0){printf("[%s@%s %s]# ", user, getenv("HOSTNAME"), dir);}else{printf("[%s@%s %s]$ ", user, getenv("HOSTNAME"), dir);}fflush(stdout);// 获取用户输入fgets(commandLine, sizeof(commandLine) - 1, stdin);commandLine[strlen(commandLine) - 1] = 0;command_check(commandLine);// 字符串切割myArgv[0] = strtok(commandLine, " ");int i = 1;// 添加、更改参数if (myArgv[0] != NULL && strcmp(myArgv[0], "ls") == 0){myArgv[i++] = (char*)"--color=auto";}if (myArgv[0] != NULL && strcmp(myArgv[0], "ll") == 0){myArgv[0] = (char*)"ls";myArgv[i++] = (char*)"-l";myArgv[i++] = (char*)"--color=auto";}// 存储参数while (myArgv[i++] = strtok(NULL, " ")){}// 如果是 cd 指令,无需创建子进程// 让 shell 执行对应的命令,本质是是执行系统接口 // 这种不需要子进程执行,而是让 shell 自己执行的命令,叫做内置/内建命令if (myArgv[0] != NULL && strcmp(myArgv[0], "cd") == 0){if (myArgv[1] != NULL){chdir(myArgv[1]); // 跳转目录char tmp_path[1024] = {0};getcwd(tmp_path, sizeof(tmp_path) - 1); // 将当前工作目录存入tmp_path中setenv("PWD", tmp_path, 1); // 修改环境变量}else{chdir(getenv("HOME"));setenv("PWD", getenv("HOME"), 1);}continue;}if (myArgv[0] != NULL && myArgv[1] != NULL && strcmp(myArgv[0], "echo") == 0){if (strcmp(myArgv[1], "$?") == 0){// 查看上一条指令的退出码、退出信号printf("last exit code: %d, last exit sig: %d\n", lastCode, lastSig);}else{printf("%s\n", myArgv[1]);}continue;}// 执行命令pid_t id = fork();if (id == 0){// 命令由子进程执行,重定向的工作由子进程完成// 父进程给子进程提供信息重定向int fd = 0;switch (redirType){case NONE_REDIR:break;case INPUT_REDIR:fd = open(redirFile, O_RDONLY);if (fd < 0){perror("open");exit(errno);}dup2(fd, 0);break;case OUTPUT_REDIR:case APPEND_REDIR:umask(0);int flags = O_WRONLY | O_CREAT;if (redirType == APPEND_REDIR){flags |= O_APPEND;}else{flags |= O_TRUNC;}fd = open(redirFile, flags, 0666);if (fd < 0){perror("open");exit(errno);}dup2(fd, 1);break;default:printf("bug\n");break;}execvp(myArgv[0], myArgv);exit(1);}// 父进程int status = 0;pid_t ret = waitpid(id, &status, 0);assert(ret > 0);lastCode = (status >> 8) & 0xFF;lastSig = status & 0x7F;}return 0;
}
相关文章:
【Linux后端服务器开发】Shell外壳——命令行解释器
目录 一、Shell外壳概述 二、描述Shell外壳原理的生动例子 三、C语言模拟实现Shell外壳 一、Shell外壳概述 在狭义上 , 我们称Linux操作系统的内核为 Linux 在广义上 , Linux发行版 Linux内核 外壳程序 就比如市面上现在的redhat, centos, ubuntu等等我们耳熟能详的Linux发…...
【无公网IP】在外Windows远程连接MongoDB数据库
文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 转载自cpolar极点云文章:公网远程…...
mac python3 安装virtualenv
第一步,执行安装virtualenv pip3 install virtualenv 注意:如果出现WARNING: The script virtualenv is installed in ‘/home/local/bin’ which is not on PATH. Consider adding this directory to PATH or, if you prefer to suppress this warning,…...
网络安全(自学笔记)
如果你真的想通过自学的方式入门web安全的话,那建议你看看下面这个学习路线图,具体到每个知识点学多久,怎么学,自学时间共计半年左右,亲测有效(文末有惊喜): 1、Web安全相关概念&am…...
SPSS方差分析
参考文章 导入准备好的数据 选择分析方法 选择参数 选择对比,把组别放入因子框中,把红细胞增加数放进因变量列表 勾选“多项式”,等级取默认“线性” ,继续 接着点击“事后比较”,弹出对话框,勾选“LSD” …...
【Linux】深入理解文件系统
系列文章 收录于【Linux】文件系统 专栏 关于文件描述符与文件重定向的相关内容可以移步 文件描述符与重定向操作。 可以到 浅谈文件原理与操作 了解文件操作的系统接口。 想深入理解文件缓冲区还可以看看文件缓冲区。 目录 系列文章 磁盘 结构介绍 定位数据 抽象管理…...
12.9 专用指令
目录 状态寄存器传送指令 读CPSR 写CPSR 软中断指令 协处理器指令 协处理器数据运算指令 协处理器存储器访问指令 协处理器寄存器传送指令 伪指令 空指令 LDR 指令 伪指令 状态寄存器传送指令 专门用来读写CPSR寄存器的指令 读CPSR MRS R1,CPSR R1 CPSR 写CP…...
Jvm对象回收算法-JVM(九)
上篇文章介绍了jvm运行时候对象进入老年代的场景,以及如何避免频繁fullGC。 Jvm参数设置-JVM(八) 老年代分配担保机制 这个机制的目的是为了提升效率,在minorGC之前,会有三次判断,之后再次minorGC速度会…...
SpringCloud Alibaba微服务分布式架构组件演变
文章目录 1、SpringCloud版本对应1.1 技术选型依据1.2 cloud组件演变: 2、Eureka2.1 Eureka Server : 提供服务注册服务2.2 EurekaClient : 通过注册中心进行访问2.3 Eureka自我保护 3、Eureka、Zookeeper、Consul三个注册中心的异同点3.1 CP…...
【Linux】初步理解操作系统和进程概念
一.认识操作系统 操作系统是一款纯正的 “搞管理” 的文件。 那操作系统为什么要管理文件? “管理” 又是什么? 它是怎么管理的? 为什么? 1.操作系统帮助用户,管理好底层的软硬件资源; 2.为了给用户提供一个…...
TypeScript 中的字面量类型和联合类型特性
字面量类型和联合类型是 TypeScript 中常用的类型特性。 1. 字面量类型: 字面量类型是指具体的值作为类型。例如,字符串字面量类型可以通过给定的字符串字面量来限制变量的取值范围。 let status: "success" | "error"; // status…...
react+jest+enzyme配置及编写前端单元测试UT
文章目录 安装及配置enzyme渲染测试技巧一、常见测试二、触发ant design组件三、使用redux组件四、使用路由的组件五、mock接口网络请求六、mock不需要的子组件 安装及配置 安装相关库: 首先,使用npm或yarn安装所需的库。 npm install --save-dev jest…...
自学网络安全(黑客)
一、为什么选择网络安全? 这几年随着我国《国家网络空间安全战略》《网络安全法》《网络安全等级保护2.0》等一系列政策/法规/标准的持续落地,网络安全行业地位、薪资随之水涨船高。 未来3-5年,是安全行业的黄金发展期,提前踏入…...
【unity小技巧】委托(Delegate)的基础使用和介绍
文章目录 一、前言1. 什么是委托?2. 使用委托的优点 二、举例说明1. 例12. 例2 三、案例四、泛型委托Action和Func1. Action委托2. Func委托 五、参考六、完结 一、前言 1. 什么是委托? 在Unity中,委托(Delegate)是一…...
【MySQL必知必会】第24章 使用游标(学习笔记)
游标 游标(cursor)是一个存储在MySQL服务器上的数据库查询,它不是一条select语句,而是被该语句检索出来的结果集游标主要用于交互式应用,其中用户需要滚动屏幕上的数据,并对数据进行浏览或做出更改只能用于存储过程,不…...
rosbag回放指定话题外的其他话题的方法
假设要回放file.bag包中除/tf话题外的所有话题 方法一 将原本/tf话题转发到另一个“黑洞话题”去,这样/tf话题就没输出了 rosbag play file.bag /tf:/tf_dev_null方法二 使用filter选项,重新生产一个新的不含/tf话题的包 rosbag filter file.bag fi…...
6.2.1 网络基本服务---域名解析系统DNS
6.2.1 网络基本服务—域名解析系统DNS 因特网是需要提供一些最基本的服务的,今天我们就来讨论一下这些基本的服务。 域名系统(DNS)远程登录(Telnet)文件传输协议(FTP)动态主机配置协议&#x…...
通用文字识别OCR 之实现自动化办公
摘要 随着技术的发展,通用文字识别(OCR)已经成为现代办公环境中不可或缺的工具之一。OCR技术可以将印刷或手写文本转换为可编辑或可搜索的数字文本,极大地提高了办公效率并实现了自动化办公。本文将深入探讨OCR技术在实现自动化办…...
Spring Boot 有哪些特点?
目录 一、自动配置 二、嵌入式 Tomcat Web 服务器 三、入门 POM 四、Actuator执行器 API 五、SpringBoot初始化器 一、自动配置 Spring Boot的自动配置是Spring Boot框架提供的一种功能,它可以根据用程序的依赖和配置信息,自动配置一些常见的功能模…...
10个图像处理的Python库
在这篇文章中,我们将整理计算机视觉项目中常用的Python库,如果你想进入计算机视觉领域,可以先了解下本文介绍的库,这会对你的工作很有帮助。 1、PIL/Pillow Pillow是一个通用且用户友好的Python库,提供了丰富的函数集…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
Vue 3 + WebSocket 实战:公司通知实时推送功能详解
📢 Vue 3 WebSocket 实战:公司通知实时推送功能详解 📌 收藏 点赞 关注,项目中要用到推送功能时就不怕找不到了! 实时通知是企业系统中常见的功能,比如:管理员发布通知后,所有用户…...
车载诊断架构 --- ZEVonUDS(J1979-3)简介第一篇
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
