Linux——简单的Shell程序

文章目录
- 一、Shell程序思路
- 二、Shell代码展示
一、Shell程序思路
用下图的时间轴来表示事件的发生次序。其中时间从左向右。shell由标识为sh的方块代表,它随着时间的流逝从左向右移动。shell从用户读入字符串"ls"。shell建立一个新的进程,然后在那个进程中运行ls程序并等待那个进程结束。

然后shell读取新的一行输入,建立一个新的进程,在这个进程中运行程序 并等待这个进程结束。
- 获取命令行
- 解析命令行
- 建立一个子进程(fork)
- 替换子进程(execvp)
- 父进程等待子进程退出(wait)
根据这些思路,和我们前面的学的技术,就可以自己来实现一个shell了。
二、Shell代码展示
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>#define NUM 1024
#define SIZE 64
#define SEP " "
//#define Debug 1char cwd[1024];
char enval[1024]; // for test
int lastcode = 0;char *homepath()
{char *home = getenv("HOME");if(home) return home;else return (char*)".";
}const char *getUsername()
{const char *name = getenv("USER");if(name) return name;else return "none";
}
const char *getHostname()
{const char *hostname = getenv("HOSTNAME");if(hostname) return hostname;else return "none";
}
const char *getCwd()
{const char *cwd = getenv("PWD");if(cwd) return cwd;else return "none";
}
int getUserCommand(char *command, int num)
{printf("[%s@%s %s]# ", getUsername(), getHostname(), getCwd());char *r = fgets(command, num, stdin); // 最终你还是会输入\nif(r == NULL) return -1;// "abcd\n" "\n"command[strlen(command) - 1] = '\0'; // 有没有可能越界?不会return strlen(command);
}void commandSplit(char *in, char *out[])
{int argc = 0;out[argc++] = strtok(in, SEP);while( out[argc++] = strtok(NULL, SEP));#ifdef Debugfor(int i = 0; out[i]; i++){printf("%d:%s\n", i, out[i]);}
#endif
}int execute(char *argv[])
{pid_t id = fork();if(id < 0) return -1;else if(id == 0) //child{// exec commandexecvp(argv[0], argv); // cd ..exit(1);}else // father{int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){lastcode = WEXITSTATUS(status);}}return 0;
}void cd(const char *path)
{chdir(path);char tmp[1024];getcwd(tmp, sizeof(tmp));sprintf(cwd, "PWD=%s", tmp); // bugputenv(cwd);
}// 什么叫做内键命令: 内建命令就是bash自己执行的,类似于自己内部的一个函数!
// 1->yes, 0->no, -1->err
int doBuildin(char *argv[])
{if(strcmp(argv[0], "cd") == 0){char *path = NULL;if(argv[1] == NULL) path=homepath();else path = argv[1];cd(path);return 1;}else if(strcmp(argv[0], "export") == 0){if(argv[1] == NULL) return 1;strcpy(enval, argv[1]);putenv(enval); // ???return 1;}else if(strcmp(argv[0], "echo") == 0){if(argv[1] == NULL){printf("\n");return 1;}if(*(argv[1]) == '$' && strlen(argv[1]) > 1){ char *val = argv[1]+1; // $PATH $?if(strcmp(val, "?") == 0){printf("%d\n", lastcode);lastcode = 0;}else{const char *enval = getenv(val);if(enval) printf("%s\n", enval);else printf("\n");}return 1;}else {printf("%s\n", argv[1]);return 1;}}else if(0){}return 0;
}int main()
{while(1){char usercommand[NUM];char *argv[SIZE];// 1. 打印提示符&&获取用户命令字符串获取成功int n = getUserCommand(usercommand, sizeof(usercommand));if(n <= 0) continue;// 2. 分割字符串// "ls -a -l" -> "ls" "-a" "-l"commandSplit(usercommand, argv);// 3. check build-in commandn = doBuildin(argv);if(n) continue;// 4. 执行对应的命令execute(argv);}
}
相关文章:
Linux——简单的Shell程序
📘北尘_:个人主页 🌎个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上,不忘来时的初心 文章目录 一、Shell程序思路二、Shell代码展示 一、Shell程序思路 用下图的时间轴来表示事件的发生次序…...
计算机网络-网络互联与互联网(一)
1.常用网络互联设备: 1层物理层:中继器、集线器2层链路层:网桥、交换机3层网络层:路由器、三层交换机4层以上高层:网关 2.网络互联设备: 中继器Repeater、集线器Hub(又叫多端口中继器…...
Android 解决后台服务麦克风无法录音问题
Android 解决后台无法录音问题 问题分析问题来源解决方案1. 修改清单文件:`AndroidManifest.xml`2. 修改启动服务方式3. 服务启动时创建前台通知并且指定前台服务类型参考文档最后我还有一句话要说我用心为你考虑黄浦江的事情,你心里想的却只有苏州河的勾当 问题分析 安卓9.…...
【计网】TCP的三次握手四次挥手
🍎个人博客:个人主页 🏆个人专栏:JAVA ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 三次握手(Connection Establishment) 四次挥手(Connection Termination) 结语 我…...
android pdf框架-4,分析vudroid源码2
继续分析源码 阅读器的入口 MainBrowserActivity,这个是主ui,由于代码较旧,所以没有处理sdcard的权限. 一般阅读器申请整个卡的读写. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {if (!Environment.isExternalStorageManager()) {Intent intent = new Intent…...
[算法沉淀记录] 排序算法 —— 希尔排序
排序算法 —— 希尔排序 算法介绍 希尔排序(Shell Sort)是一种基于插入排序的算法,由Donald Shell于1959年提出。希尔排序的基本思想是将待排序的序列划分成若干个子序列,分别进行插入排序,待整个序列中的记录基本有…...
conda 进入虚拟环境命令报错
问题描述 conda-script.py: error: argument COMMAND: invalid choice: activate 解决方案: 在终端命令先执行 conda init,重置conda环境。然后退出终端,重新进入终端即可conda activate env了。...
域名 SSL 证书信息解析 API 数据接口
域名 SSL 证书信息解析 API 数据接口 网络工具,提供域名 SSL 证书信息解析,多信息查询,毫秒级响应。 1. 产品功能 提供域名 SSL 证书信息解析;最完整 SSL 属性信息解析;支持多种元素信息抽取,包括主题的可…...
学习JAVA的第二天(基础)
目录 基本概念 关键字 class关键字 字面量 练习 变量 定义格式 变量使用 数据类型 基本数据类型 标识符 命名规则 键盘录入 1.导包 2.创建对象 3.接受数据 运算符 算术运算符 练习 隐式转换(自动类型提升) 强制转换 自增自减运算符 …...
代码随想录算法训练营第二十七天|93.复原IP地址、78.子集、90.子集II
93.复原IP地址 刷题https://leetcode.cn/problems/restore-ip-addresses/description/文章讲解https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html视频讲解https://www.bilibili.com/video/BV1XP4y1U73i/?vd_sourceaf4853e80f89e28094a5fe1e220d9…...
【蓝桥备赛】字串简写
字串简写 数据范围 字符串的长度为5*10的五次方,on方时间复杂度会很大。 才用动态规划的思想,dp[i]以i开头的的可能性,因为长度必须大于等于k,当i小于k的时候,如果等于第一个字符,s1时,dp[…...
nios ii开发随笔
错误一: d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_64-mingw32/bin/../lib/gcc/nios2-elf/5.3.0/../../../../../H-x86_64-mingw32/nios2-elf/bin/ld.exe: test.elf section .text will not fit in region ram_oc_xzs d:/intelfpga/17.1/nios2eds/bin/gnu/h-x86_6…...
SpringBoot项目嵌入RabbitMQ
在Spring Boot中嵌入RabbitMQ可以通过添加相应的依赖来完成。首先需要在pom.xml文件中引入spring-boot-starter-amqp依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</a…...
提升网络质量:UDPspeeder 实现网络优化与提速
提升网络质量:UDPspeeder 实现网络优化与提速 背景与意义原理与功能使用方法未来展望相关链接服务 在当今高度互联的网络环境下,网络质量的优化和提速对于用户体验至关重要。针对高延迟和丢包率较高的网络链路,UDPspeeder 提供了一种前向纠错…...
为什么前端开发变得越来越复杂了?这可能是我们的错
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello,大家好,我是 Sunday。 最近有很多同学来问我:“Sunday 老师,前端学起…...
VR系统的开发流程
虚拟现实(Virtual Reality,VR)系统是一种通过计算机技术模拟出的具有三维视角和交互性的虚拟环境,使用户能够沉浸在其中并与虚拟环境进行交互。这种技术通常利用头戴式显示器和手柄等设备,使用户能够感觉到仿佛身临其境…...
前端输入框校验限制不能输入中文
一般我们在做表单的时候都会有表单校验,通常都是用element提供的表单验证的功能,只需要通过 rules 属性传入约定的验证规则,如下面这样 rules: {userName: [{validator: checkUsername,trigger: "blur",},{ validator: this.checkData, trigge…...
强大的文本绘图——PlantUML
PlantUML是一款开源工具,它允许用户通过简单的文本描述来创建UML图(统一建模语言图)。这种方法可以快速地绘制类图、用例图、序列图、状态图、活动图、组件图和部署图等UML图表。PlantUML使用一种领域特定语言(DSL)&am…...
ES相关问题
在Elasticsearch(ES)集群中,节点根据其配置和角色可以分为以下几种主要类型: Master Node(主节点): 主节点负责管理整个集群的元数据,如索引的创建、删除、分片分配等。它维护着集群…...
基于Linux直接安装的Nginx版本升级方法
引言 随着版本的迭代和漏洞的发现,Nginx作为一款软件避免不了打补丁的命运。 以下基于Linux直接安装的Nginx版本升级。 以下操作均在本地虚拟机中操作验证,请验证后再线上操作。基于centos7测试。 前置资源 获取nginx的最新源码版本网址:…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序
一、开发环境准备 工具安装: 下载安装DevEco Studio 4.0(支持HarmonyOS 5)配置HarmonyOS SDK 5.0确保Node.js版本≥14 项目初始化: ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...
JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作
一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...
解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
MFE(微前端) Module Federation:Webpack.config.js文件中每个属性的含义解释
以Module Federation 插件详为例,Webpack.config.js它可能的配置和含义如下: 前言 Module Federation 的Webpack.config.js核心配置包括: name filename(定义应用标识) remotes(引用远程模块࿰…...
使用SSE解决获取状态不一致问题
使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...
智能职业发展系统:AI驱动的职业规划平台技术解析
智能职业发展系统:AI驱动的职业规划平台技术解析 引言:数字时代的职业革命 在当今瞬息万变的就业市场中,传统的职业规划方法已无法满足个人和企业的需求。据统计,全球每年有超过2亿人面临职业转型困境,而企业也因此遭…...
基于Uniapp的HarmonyOS 5.0体育应用开发攻略
一、技术架构设计 1.混合开发框架选型 (1)使用Uniapp 3.8版本支持ArkTS编译 (2)通过uni-harmony插件调用原生能力 (3)分层架构设计: graph TDA[UI层] -->|Vue语法| B(Uniapp框架)B --&g…...
欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!
多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…...
Element-Plus:popconfirm与tooltip一起使用不生效?
你们好,我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip,产品要求是两个需要结合一起使用,也就是鼠标悬浮上去有提示文字,并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...
