Linux实现简易shell

news2024/11/22 16:13:06

在这里插入图片描述

文章目录

    • 🦄0. shell
    • 🐮1. 交互及获取命令行
    • 🐷2. 解析命令行
    • 🐯3. 执行命令行
      • 🐅3.1 普通命令
      • 🐅3.2 内建命令
    • 🦁4. 主函数逻辑及演示

本章代码gitee仓库:简易shell

🦄0. shell

shell是操作系统外的一层外壳程序,负责将用户的指令执行,将指令获取到之后再交给操作系统,操作系统将指令执行完毕之后的结果通过shell交给用户。shell/bash也是一个进程,本质上也是通过创建子进程来执行这些指令。

🐮1. 交互及获取命令行

我们先来开一下交互及我们输入的命令行格式

image-20231103220238498

先来做交互的页面,这其实就是一个while循环,一直等着我们输入指令,我们可以通过获取环境变量来获取这些信息。

#define LEFT "["
#define RIGHT "]"
#define LABLE "#"
const char *getUserName()
{
  return getenv("USER");
}
const char *getHostName()
{
  return getenv("HOSTNAME");
}
void getPwd()
{
  getcwd(pwd,sizeof(pwd));
}
void interact(char *cline, int size)
{
  getPwd();
  printf(LEFT"%s@%s %s"RIGHT""LABLE" ",getUserName(),getHostName(),pwd);
  char *s = fgets(cline,size,stdin);	//获取指令
  assert(s);
  (void)s;  //防止后面不使用s变量报警告,假装用一下
  cline[strlen(cline)-1] = '\0';  //将回车抵消
  //printf("%s\n",s);
}

我们可以输出我们获取的命令测试一下

image-20231103221103250

🐷2. 解析命令行

获取到命令之后,我们就要解析这个命令,这个解析的本质上,就是将获取的字符串进行分割,分割各个部分:要执行的命令所带的命令行参数

例如ls -a -l,我们就需要解析成:

  • 所需执行的命令:ls
  • 命令行参数:-a-l
#define DELIM " \t"
int splitString(char cline[], char *_argv[])
{
  int i = 0;
  _argv[i++] = strtok(cline,DELIM);
  while(_argv[i++] = strtok(NULL,DELIM));
  return i-1;
}

image-20231103221728909

🐯3. 执行命令行

获取到所需执行的命令和参数之后,其实就是创建子进程,然后程序替换来执行这个命令,但是这些命令分为普通命令和内建命令:

  • 普通命令:创建子进程直接程序替换
  • 内建命令:父进程自己执行

🐅3.1 普通命令

这里没有什么高科技,就是简单的创建子进程、程序替换和进程等待

#define EXIT_CODE 11
void normalExcute(char *_argv[])
{
  pid_t id = fork();
  if(id < 0)
  {
    perror("fork fail");
    return; 
  }
  else if(id == 0)
  {
    //子进程执行命令
    //execvpe(_argv[0],_argv,environ);  //直接程序替换
    execvp(_argv[0],_argv);   //直接替换程序
    exit(EXIT_CODE);  //替换失败的退出码
  }
  else
  {
    //父进程等待子进程退出
    int status = 0;
    pid_t rid = waitpid(id,&status,0);  //阻塞等待
    if(rid == id)
    {
      lastcode = WEXITSTATUS(status);
    }
  }
}

🐅3.2 内建命令

对应内建命令,需要我们自己去一个一个添加然后判断,这里做一个简单的演示

int buildCommand(char *_argv[], int _argc)
{
  if(_argc == 2 && strcmp(_argv[0],"cd") == 0)
  {
    chdir(_argv[1]);
    getPwd();
    sprintf(getenv("PWD"),pwd);
    return 1;
  }
  else if(_argc == 2 && strcmp(_argv[0],"export") == 0) //导环境变量
  {
    putenv((char*)_argv[1]);
    return 1;
  }
  else if(_argc == 2 && strcmp(_argv[0],"echo") == 0)                                 
  {
    if(strcmp(_argv[1],"$?")==0)
    {
      printf("%d\n",lastcode);
      lastcode = 0;
    }
    else if(*_argv[1] == '$')
    {
      char*val = getenv(_argv[1]+1);
      if(val) printf("%s\n",val);
    }
    else  printf("%s\n",_argv[1]);

    return 1;
  }
  //将ls命令显示颜色
  if(strcmp(_argv[0],"ls") == 0)
  {
    _argv[_argc++] = "--color";
    _argv[_argc] = NULL;
  }
  return 0;
}

🦁4. 主函数逻辑及演示

这里我们全部都封装起来了,各个模块解耦,想要修改的话,也很方便,完整的代码可以去仓库里面查看。

#define LINE_SIZE 1024
#define ARGC_SIZE 32

int main()
{
  while(!quit)
  {
    //交互 获取命令行
    interact(commandline,sizeof(commandline));
    
    //解析命令行
    int argc = splitString(commandline,argv);
    if(argc == 0) continue;
    //for(int i=0;argv[i];i++) printf("%s\n",argv[i]);
    //printf("%s\n",argv);
    //普通命令执行
    int flag = buildCommand(argv,argc);
    if(!flag) normalExcute(argv);
  }
  return 0;
}

GIF 2023-11-3 22-37-06
所以我们每次登录的时候,界面会显示这些信息,其实就是因为系统启动了一个shell进程。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python自动化测试如何自动生成测试用例?

传统的测试用例需要测试或者开发人员将用户的操作用代码表示出来&#xff0c;通过断言判断是否和预期一致&#xff0c;写测试用例也占用了部分时间&#xff0c;加上版本迭代测试用例的维护成本也较高&#xff0c;于是基于无埋点的需求相结合自动化测试来检测埋点&#xff0c;及…

行情分析——加密货币市场大盘走势(11.3)

大饼昨日与今日目前都是下跌态势&#xff0c;近期依然要保持逢低做多的策略。现在下跌&#xff0c;可以继续等待&#xff0c;也可以入场一部分仓位的多单&#xff0c;回调才是给机会上车。MACD日线来看&#xff0c;会继续回调&#xff0c;因此这个位置还是可以在等等。 以太昨日…

实践笔记-docker-compose安装

docker-compose 1.在线安装2.离线安装 1.在线安装 # github下载&#xff08;太慢了或者直接下载不了&#xff09; curl -L https://github.com/docker/compose/releases/download/1.25.4/docker-compose-uname -s-uname -m -o /usr/local/bin/docker-compose # daocloud下载 c…

【MySQL】015-MySQL索引

【MySQL】015-MySQL索引 文章目录 【MySQL】015-MySQL索引一、MySQL索引是什么1、概述2、好处3、缺点4、索引的使用场景5、常用命令查看数据表上建的索引 二、索引的分类1、三大类2、为什么使用B树作为索引在疑问为什么使用B树这种数据结构之前&#xff0c;先想想什么样的数据结…

网络编程——以太网协议

一&#xff0c;以太网格式 1.1目的地址 这个地址不是IP地址&#xff0c;而是网络中的另一套地址体系&#xff0c;mac 地址&#xff08;物理地址&#xff09;&#xff0c;这个地址的作用与IP地址有一定的重合。因为网络层协议与应用层协议是各自独立被开发的&#xff0c;所以地…

黄仁勋:英伟达预言 2 年内行业将面目全非 一个词形容AI:Unbelievable

本心、输入输出、结果 文章目录 黄仁勋&#xff1a;英伟达预言 2 年内行业将面目全非 一个词形容AI&#xff1a;Unbelievable前言【访谈内容】一个词形容AI&#xff1a;Unbelievable创立英伟达“比想象中难一百万倍”相关图片传送门弘扬爱国精神 黄仁勋&#xff1a;英伟达预言 …

贷款行业极难获客,怎么获取实时客户数据?

我们能想象当客户有贷款需求时会发生什么吗&#xff1f; 客户可能会打开手机搜索“如何借款”、“哪笔贷款利息低”、“最多能借多少钱”、“贷款需要什么条件”等关键词&#xff0c;然后&#xff0c;客户点击进入第一个链接&#xff0c;然后填写他们的姓名和电话号码来测试他…

浅谈无源供电无线测温在线监测系统应用方案

安科瑞 崔丽洁 摘要&#xff1a;无源供电无线测温在线监测系统是一种基于声表面波技术的测温技术&#xff0c;在变电站监测方面得到了很好的技术实践应用。本文对无源供电无线测温在线监测系统研究应用进行分析研究。 关键词&#xff1a;设备检测&#xff1b;无线测温。 引言 在…

vcruntime140.dll无法继续执行代码修复教程

在计算机的世界里&#xff0c;我们经常会遇到各种各样的问题&#xff0c;其中之一就是“vcruntime140.dll缺失”。这个问题可能会影响到我们的正常使用&#xff0c;但是别担心&#xff0c;今天我就来给大家分享一下关于vcruntime140.dll缺失的4种修复方案。 首先&#xff0c;我…

C#完成XML文档节点的自动计算功能

一个项目涉及XML文档中节点的自动计算&#xff0c;就是XML文档的每个节点都参与运算&#xff0c;要求&#xff1a; ⑴如果节点有计算公式则按照计算公式进行&#xff1b; ⑵如果节点没有计算公式则该节点的值就是所有子节点的值之和&#xff1b; ⑶节点有4种类型&#xff0c;计…

内网穿透实现远程访问,如何满足信息安全需求?

内网穿透技术是一种将内网服务映射到外网&#xff0c;从而实现远程访问的技术。它的出现为企业及个人带来了便利&#xff0c;但同时也带来了一定的安全风险。因此&#xff0c;确保内网穿透远程访问内网服务的安全性显得尤为重要。 贝锐旗下内网穿透兼动态域名解析品牌花生壳&am…

【漏洞库】XXL-JOB executor 未授权访问漏洞导致RCE

文章目录 漏洞描述漏洞编号漏洞评级影响版本漏洞复现- EXP 编写 漏洞挖掘修复建议 漏洞描述 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。XXL-JOB分为adm…

TCP四次挥手过程解密:为什么不止三次挥手或更少次挥手?

&#x1f3ac; 江城开朗的豌豆&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 &#x1f4dd; 个人网站 :《 江城开朗的豌豆&#x1fadb; 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 ⭐ 专栏简介 &#x1f4d8; 文章引言 一、三…

使用Postman工具做接口测试 —— 断言与参数提取

引言 下面我会以登录为例&#xff0c;来讲如何利用postman提取上一个接口返回数据&#xff0c;并且放到当前接口来使用。 接口关联(参数提取) 下面以登录接口为例&#xff0c;讲一下postman如何使用参数提取&#xff0c;可以通过Fiddler工具对系统登录操作进行抓包分析&#…

linux报错汇总

1. linux 安装pytorch报错 CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/linux-64/current_repodata.json> Elapsed: -An HTTP error occurred when trying to retrieve this URL. HTTP errors are o…

基于 Amazon EC2 和 Amazon Systems Manager Session Manager 的堡垒机的设计和自动化实现

文章目录 1. 背景2. 云上堡垒机设计2.1 安全设计2.2 高可用和弹性设计2.3 监控告警设计2.4 自动化部署设计2.4.1 堡垒机代码设计2.4.2 Session Manager 配置设计2.4.3 堡垒机 IAM 角色设计 3. 部署堡垒机3.1 堡垒机部署架构图3.2 堡垒机自动化部署 4. 堡垒机使用场景4.1 堡垒机…

[python 刷题] 2866 Beautiful Towers II

[python 刷题] 2866 Beautiful Towers II 题目如下&#xff1a; You are given a 0-indexed array maxHeights of n integers. You are tasked with building n towers in the coordinate line. The ith tower is built at coordinate i and has a height of heights[i]. A co…

Wi-Fi还可以做什么?柯南解释IOT应用

大会报告&#xff1a;无线人工智能技术正在改变世界 Wi-Fi还可以做什么&#xff1f;随着带宽的提升&#xff0c;无线终端可以识别出更多的多径&#xff0c;每条多径都可以视作一个虚拟传感器&#xff0c;以感知周边环境。基于此&#xff0c;越来越多的无线感知产品应运而生。20…

Leetcode1122. 数组的相对排序

Every day a Leetcode 题目来源&#xff1a;1122. 数组的相对排序 解法1&#xff1a;哈希 用集合 set 存储 arr2 中的元素。 遍历数组 arr1 &#xff0c;设当前元素为 num&#xff1a; 如果 num 在 set 中出现&#xff0c;用哈希表 hash 记录 num 和它出现的次数。否则&a…

【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG(目前没有完全的解决方案)

【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG&#xff08;目前没有完全的解决方案&#xff09; GNSS配置如下&#xff1a; 【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取&#xff08;北斗、GPS和GNSS&#xff09; 测试视频&#xff08;包括BUG复…