【Linux】手把手教你做一个简易shell(命令行解释器)

简介: 【Linux】手把手教你做一个简易shell(命令行解释器)

> 作者简介:დ旧言~,目前大二,现在学习Java,c,c++,Python等

> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:自己能写出一个简易shell(命令行解释器)

> 毒鸡汤:要让人觉得毫不费力,只能背后极其努力。

> 望小伙伴们点赞👍收藏✨加关注哟💕💕  



原理:

       shell是命令行解释器,当有命令需要执行时,shell创建子进程,让子进程执行命令,而shell只需等待子进程退出即可。



实现思路:

  • 获取命令行(fgets函数)。
  • 解析命令行(strtok分割字符串)。
  • 创建子进程(fork函数)。
  • 替换子进程(exec函数族)。
  • 等待子进程退出(waitpid函数)。


代码如下:

#include <stdio.h>
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LEN 1024 //命令最大长度
#define NUM 32 //命令拆分后的最大个数
int main()
{
  char cmd[LEN]; //存储命令
  char* myargv[NUM]; //存储命令拆分后的结果
  char hostname[32]; //主机名
  char pwd[128]; //当前目录
  while (1){
    //获取命令提示信息
    struct passwd* pass = getpwuid(getuid());
    gethostname(hostname, sizeof(hostname)-1);
    getcwd(pwd, sizeof(pwd)-1);
    int len = strlen(pwd);
    char* p = pwd + len - 1;
    while (*p != '/'){
      p--;
    }
    p++;
    //打印命令提示信息
    printf("[%s@%s %s]$ ", pass->pw_name, hostname, p);
    //读取命令
    fgets(cmd, LEN, stdin);
    cmd[strlen(cmd) - 1] = '\0';
    //拆分命令
    myargv[0] = strtok(cmd, " ");
    int i = 1;
    while (myargv[i] = strtok(NULL, " ")){
      i++;
    }
    pid_t id = fork(); //创建子进程执行命令
    if (id == 0){
      //child
      execvp(myargv[0], myargv); //child进行程序替换
      exit(1); //替换失败的退出码设置为1
    }
    //shell
    int status = 0;
    pid_t ret = waitpid(id, &status, 0); //shell等待child退出
    if (ret > 0){
      printf("exit code:%d\n", WEXITSTATUS(status)); //打印child的退出码
    }
  }
  return 0;
}


运行结果:



说明:

当执行./myshell命令后,便是我们自己实现的shell在进行命令行解释,我们自己实现的shell在子进程退出后都打印了子进程的退出码,我们可以根据这一点来区分我们当前使用的是Linux操作系统的shell还是我们自己实现的shell。


🌟结束语

      今天内容就到这里啦,时间过得很快,大家沉下心来好好学习,会有一定的收获的,大家多多坚持,嘻嘻,成功路上注定孤独,因为坚持的人不多。那请大家举起自己的小手给博主一键三连,有你们的支持是我最大的动力💞💞💞,回见。


目录
相关文章
|
11月前
|
算法 Linux Shell
Linux实用技能:打包压缩、热键、Shell与权限管理
本文详解Linux打包压缩技巧、常用命令与原理,涵盖.zip与.tgz格式操作、跨系统传文件方法、Shell运行机制及权限管理,助你高效使用Linux系统。
Linux实用技能:打包压缩、热键、Shell与权限管理
|
11月前
|
存储 安全 Unix
七、Linux Shell 与脚本基础
别再一遍遍地敲重复的命令了,把它们写进Shell脚本,就能一键搞定。脚本本质上就是个存着一堆命令的文本文件,但要让它“活”起来,有几个关键点:文件开头最好用#!/usr/bin/env bash来指定解释器,并用chmod +x给它执行权限。执行时也有讲究:./script.sh是在一个新“房间”(子Shell)里跑,不影响你;而source script.sh是在当前“房间”里跑,适合用来加载环境变量和配置文件。
902 9
|
11月前
|
存储 Shell Linux
八、Linux Shell 脚本:变量与字符串
Shell脚本里的变量就像一个个贴着标签的“箱子”。装东西(赋值)时,=两边千万不能有空格。用单引号''装进去的东西会原封不动,用双引号""则会让里面的$变量先“变身”再装箱。默认箱子只能在当前“房间”(Shell进程)用,想让隔壁房间(子进程)也能看到,就得给箱子盖个export的“出口”戳。此外,Shell还自带了$?(上条命令的成绩单)和$1(别人递进来的第一个包裹)等许多特殊箱子,非常有用。
968 2
|
Web App开发 缓存 安全
Linux一键清理系统垃圾:释放30GB空间的Shell脚本实战​
这篇博客介绍了一个实用的Linux系统盘清理脚本,主要功能包括: 安全权限检查和旧内核清理,保留当前使用内核 7天以上日志文件清理和系统日志压缩 浏览器缓存(Chrome/Firefox)、APT缓存、临时文件清理 智能清理Snap旧版本和Docker无用数据 提供磁盘空间使用前后对比和大文件查找功能 脚本采用交互式设计确保安全性,适合定期维护开发环境、服务器和个人电脑。文章详细解析了脚本的关键功能代码,并给出了使用建议。完整脚本已开源,用户可根据需求自定义调整清理策略。
1308 1
|
Linux 数据安全/隐私保护
使用Linux命令行接入无线网络Wi-Fi的示例。
现在,你已经使用命令行成功地连接到 Wi-Fi 网络了。这两个示例涵盖了用 `nmcli` 和 `wpa_supplicant` 连接无线网络的常见场景,让你能够不依赖图形化界面来完成这个任务。在日常使用中熟练掌握这些基本操作能增强你对 Linux 系统的理解,帮助你更有效地处理各种问题。
1154 12
|
Java Linux 开发工具
Linux下版本控制器(SVN) -命令行客户端
Linux下版本控制器(SVN) -命令行客户端
431 4
|
Linux Shell
Centos或Linux编写一键式Shell脚本删除用户、组指导手册
Centos或Linux编写一键式Shell脚本删除用户、组指导手册
431 4
|
Linux Shell 数据安全/隐私保护
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
Centos或Linux编写一键式Shell脚本创建用户、组、目录分配权限指导手册
700 3