Linux mybash

news2024/11/20 13:27:18

shell

在了解bash之前 我们要先了解shell

Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。

Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。

可以称之为壳程序,用于用户与操作系统进行交互。用来区别与核,相当于是一个命令解析器,Shell有很多中,这里列出其中几种

Bourne SHell(sh)
Bourne Again SHell(bash)
C SHell(csh)
KornSHell(ksh)
zsh
各个shell的功能都差不太多,在某些语法的下达下面有些区别,Linux预设就是bash。

bash命令是sh命令的超集,大多数sh脚本都可以在bash下运行,bash主要有如下这些功能

bash功能
记录历史命令:bash可以记录曾经的命令,保持在~/.bash_history文件中,只保存上次注销登录之后的命令
tab键自动补全:使用tab见可以自动不全命令或者目录i
alias命令别名:可以使用alias ll='ls -al'来设置命令的别名
工作控制:可以将某些任务放在后台去运行,这里不多种介绍
程序脚本:可以执行shell脚本文件
通配符:在查找相关文件或者执行相关命令时,可以使用通配符*
内建命令type:可以使用type 命令来查看某个命令是否为内建在bash当中的命令「
bash变量
bash中变量有两种,分别是环境变量和自定义变量,可以理解为全局变量和局部变量,在理解他们的区别前,需要知道父程序和子程序,举个例子,当前的bash我们称之为父程序,而在这个bash下执行的任何程序,都称之为子程序。那全局变量和局部变量的区别就是,全局变量在子程序中仍然有效,局部变量只在当前程序中生效。(注意,一旦退出父程序这个bash的话,无论是全局变量还是局部变量都失效了,再次打开bash时,该变量是不存在的)

mybash

我们可以结合bash界面 实现一个用户自定义的mybash

首先我们可以模仿终端界面 实现一个用户自用的mybash

可以看到我们的提示符包含 用户名 设备名 当前路径 权限类别

那么我们可以暂时将这个标识符 

 printf("ubuntu@localhost : ~ $ ");
        fflush(stdout);

 这样就会在界面上打印一个静态的标识符

@之前的是用户名 每个人的用户名都是自定义的 然后 @ 到:之前是设备名 ~是当前路径

$是表示当前权限是用户

那么如果我们想实现可以变动的并且可以自适应的标识符应该 怎么办呢

void printf_info(){
    char* user_str = "$";
    int user_id = getuid();
    if(user_id == 0) user_str = "#";
    struct passwd* ptr = getpwuid(user_id);
    
    char hostname[128]={0};
    gethostname(hostname,128);
    char dir[256]={0};  /
    getcwd(dir,256);
    printf("\033[1;32m%s@%s\033[0m:\033[1;34m:%s\033[0m %s ",ptr->pw_name,hostname,dir,user_str);
    fflush(stdout);
}

 这里面的函数可以获取到用户的信息

例如getuid()可以获取到权限类别

如果是管理员(超级用户)权限 他的返回值是0 我们这里就默认设计成 初始值为$

然后是 ptr这个结构体 结构体中的pw_name可以获取到用户的用户名

然后gethostname可以获取到设备名

然后我们可以在printf中看到不一样的符号

这个是可以改变字体颜色的 因为在Linux中bash界面我们可以看到 标识符是有颜色的

那么接下来我们就要实现bash的实现命令的功能

首先我们可以考虑到的是 fork+exec系列函数 来实现我们的命令

但是这里我们只能使用 execv系列函数 因为

execv系列函数的 函数参数是用数组存储的 更加利于我们对函数进行调试和修改

char* get_cmd(char* buff,char* myargv[]){
    if(buff == NULL || myargv == NULL)  return NULL;
    char* s = strtok(buff," ");
    int i = 0;
    while(s != NULL){
        myargv[i++] = s;
        s = strtok(NULL," ");
    }
    return myargv[0];
}
char* myargv[ARG_MAX] = {0};
        char* cmd = get_cmd(buff,myargv);
        if(cmd == NULL) continue;
        else if(strcmp(cmd,"cd") == 0){ //["cd"]["/bin"]
            if(myargv[1] != NULL && chdir(myargv[1]) == -1){
                perror("cd err");
            }
        }
        else if(strcmp(cmd,"exit") == 0){
            // exit(0); 
            break;
        }    
        else{ //????????
            //fork + exec  
        }
    }

这样就可以实现了我们只调用系统提供的命令来进行操作

我们也可以应用自己编译完成的可执行程序

例如自己编写的 ls pwd等

void run_cmd(char* name,char*myargv[]){
    if(name == NULL || myargv == NULL)
        return ;
    int len = strlen(name);
    if(name[len-1] == '\n')
        name[len-1]='\0';
    pid_t pid = fork();
    if(pid == -1) return;
    if(pid == 0){
        char pathname[128] = {0};
        if(strncmp(name,"/",1) == 0 || strncmp(name,"./",2) == 0){
            strcpy(pathname,name);
        }
        else{
            strcpy(pathname,PATH_BIN);
            strcat(pathname,name);
        }
        execvp(pathname,myargv);
        perror("exec err");
        exit(0);
    }
    wait(NULL);
}

这里看到我们使用了自己的可执行程序 

然后就需要引入自己的环境变量而不是使用系统的环境变量

然后里面要有自己编译的可执行程序

然后下面附上 mybash以及几个可运行程序

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <pwd.h>
#define ARG_MAX 10
#define PATH_BIN "/home/ubuntu/test/mybin/"
void run_cmd(char* name,char*myargv[]){
    if(name == NULL || myargv == NULL)
        return ;
    int len = strlen(name);
    if(name[len-1] == '\n')
        name[len-1]='\0';
    pid_t pid = fork();
    if(pid == -1) return;
    if(pid == 0){
        char pathname[128] = {0};
        if(strncmp(name,"/",1) == 0 || strncmp(name,"./",2) == 0){
            strcpy(pathname,name);
        }
        else{
            strcpy(pathname,PATH_BIN);
            strcat(pathname,name);
        }
        execvp(pathname,myargv);
        perror("exec err");
        exit(0);
    }
    wait(NULL);
}

char* get_cmd(char* buff,char* myargv[]){
    char* s = strtok(buff," ");
    int i = 0;
    while(s != NULL){
        myargv[i++] = s;
        s = strtok(NULL," ");
    }
    return myargv[0];
}

void printf_info(){
    char* user_str = "$";
    int user_id = getuid();    if(user_id == 0) user_str = "#";
    struct passwd* ptr = getpwuid(user_id);
    
    char hostname[128]={0};
    gethostname(hostname,128);
    char dir[256]={0};  
    getcwd(dir,256);
    printf("\033[1;32m%s@%s\033[0m:\033[1;34m:%s\033[0m %s ",ptr->pw_name,hostname,dir,user_str);
    fflush(stdout);
}

int main(){
    while(1){
        //printf("stu@localhost~$");
        printf_info();
        fflush(stdout);
        char buff[128]={0};
        char* myargv[ARG_MAX] = {0};
        fgets(buff,127,stdin);
        char* cmd = get_cmd(buff,myargv);
         
        if(strncmp(cmd , "cd",2) == 0){
            char buff[128]={0};
            strncpy(buff,myargv[1],strlen(myargv[1])-1);
            //
            if(buff==NULL||chdir(buff)==-1){
                perror("cd err");
            }
        }   
        else if(strncmp(cmd,"exit",4)==0){
            break;
        }
        else if(strncmp(cmd,"\n",1) == 0){
            continue;
        }
        else{
            //fork+exec
            run_cmd(cmd,myargv);
        }
    }
    exit(0);
}

 ls

#include <stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>

int main(){
      opendir(path)
    char path[128]={0};
    if(getcwd(path,128) == NULL)  exit(1);
    DIR* pdir = opendir(path);
    if(pdir == NULL)  exit(1);
   
    struct dirent* s = NULL;
    while((s=readdir(pdir)) != NULL){
        if(strncmp(s->d_name,".",1) == 0){
            continue;
        }
        struct stat filestat;
        stat(s->d_name,&filestat);  

        if(S_ISDIR(filestat.st_mode)){ 
            printf("\033[1;34m%s\033[0m     ",s->d_name);
        }
        else{ 
           if(filestat.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) { //  000100     &    0000111  -> 0000100  -> 1   true
                printf("\033[1;32m%s\033[0m    ",s->d_name);
           }
           else{
                printf("%s    ",s->d_name);
           }
        }
    }
    printf("\n");
    closedir(pdir);
    exit(0);
}

 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    char path[128]={0};
    if(getcwd(path,128) == NULL){
        perror("getcwd err");
        exit(1);
    }
    printf("%s\n",path);
    exit(0);
}

pwd

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
    printf("\033[2J\033[0;0H");
    exit(0);
}

clear 

 

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

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

相关文章

NoSQL数据库原理与应用综合项目——Neo4j篇

NoSQL数据库原理与应用综合项目——Neo4j篇 文章目录NoSQL数据库原理与应用综合项目——Neo4j篇0、 写在前面1、本地数据或HDFS数据导入到Neo4j2、Neo4j数据库表操作2.1 使用Python连接Neo4j2.2 查询数据2.3 插入数据2.4 修改数据2.5 删除数据3、Windows远程连接Neo4j(Linux)4、…

uboot源码下载以及编译

环境&#xff1a;ubuntu 20.04 uboot源码下载以及编译1 uboot源码下载&#xff1a;1.1 进入uboot官网1.2 下载源码2 编译uboot2.1 配置2.2 编译2.2.1 确认编译工具链是否ok2.2.2 配置环境变量2.2.3 编译3 注意事项3.1 uboot 2022.04版本问题3.2 unable to execute swig: No suc…

分代收集算法

将这个堆内存划分成两块&#xff1a;新生代和老年代&#xff0c;刚刚创建的对象都在新生代&#xff0c;长久存活的对象都在老年代&#xff08;老年代的垃圾回收很久发生一次&#xff0c;新生代的垃圾回收发生的比较频繁&#xff09; 新生代又进一步划分成伊甸园Eden&#xff0…

docker安装gitlab(超级详细)

前提&#xff1a; 在操作之前需要安装docker和docker-compose 拉取镜像 docker pull gitlab/gitlab-ce:15.2.4-ce.0 创建本地文件夹 mkdir /data/docker/gitlab/etc mkdir /data/docker/gitlab/logs mkdir /data/docker/gitlab/data 编写 docker-compose.yml cd /data/docker/…

面试高频题目,每周更新。

1.如何实现一个div快速的居中对齐&#xff1f; 2.margin和padding有什么不同&#xff1f; 作用对象不同&#xff0c;margin是针对对外部对象&#xff0c;padding是针对于自身。 3.vw和百分比有什么区别&#xff1f; 百分比是有继承的&#xff0c;父级元素改变后&#xff0c;会…

删除的照片如何恢复? 5个照片恢复方法总结

有人说&#xff0c;照片承载着很多回忆&#xff0c;一些难忘的时刻&#xff0c;还有一些经历。这就是我们不能丢失它们的原因&#xff0c;如果偶然丢失它们&#xff0c;到目前为止还没有可靠的设备。但是&#xff0c;如果您丢失了一些照片并想找回它们&#xff0c;请不要担心&a…

MySQL集群解决方案(4):负载均衡

在前面架构中&#xff0c;虽然对mycat做了集群&#xff0c;保障了mycat的可靠性&#xff0c;但是&#xff0c;应用程序需要连接到多个mycat&#xff0c;显然不是很友好的&#xff0c;也就是说缺少负载均衡的组件&#xff0c;接下来我们来了解下HAProxy。 1 简介 官网&#xff…

Nacos安装-单机安装

目录 一、环境介绍 二、安装方式 三、部署模式 四、单机模式包部署 4.1 下载到对应地址 4.2 解压缩包 4.3 单机模式支持mysql 导入初始化SQL 修改配置文件 4.4. 单机模式启动nacos 启动成功 登录 一、环境介绍 操作系统&#xff1a;Ubuntu 20.04.1JDK&#xff1a;保证…

HaaS EDU物联网项目实战:老板来了

HaaS EDU K1是一款高颜值、高性能、高集成度的物联网开发板&#xff0c;板载功能强大的4核&#xff08;双核300Mhz M33双核1GHz A7&#xff09;主芯片&#xff0c;2.4G/5G双频Wi-Fi&#xff0c;双模蓝牙&#xff08;经典蓝牙/BLE&#xff09;&#xff0c;并自带丰富的传感器与小…

2023 年的 7 个技术趋势——人工智能与企业内容管理相结合,云成为企业 IT 标准, 数据民主化······

2023 年的 7 个技术趋势 技术的发展速度比以往任何时候都快。高通胀、供应链问题和技术工人短缺等经济因素给当今的企业带来了巨大的压力。艰难的经济环境促使公司重新评估其财务战略&#xff0c;并寻找保持利润率的方法&#xff0c;同时培养对不断变化的经济状况做出快速反应…

又一款AR HUD前装量产上车!这家供应商深耕HUD行业8年

12月15日晚&#xff0c;岚图汽车首款轿车——岚图追光正式首发亮相并开启预售。预售价分别为32.29万元、35.29万元、43.29万元。 作为岚图汽车首个搭载ESSASOA智能电动仿生体的量产车型&#xff0c;领先的技术架构保证岚图追光在性能、智能、豪华、安全等各维度的表现都达到同级…

【数据结构-排序】内部排序

文章目录1 直接插入排序1.1 算法简要思想1.2 算法特性2 希尔排序2.1 算法简要思想2.2 手动模拟2.3 算法特性3 冒泡排序3.1 算法简要思想3.2 算法特性4 快速排序4.1 算法思路4.2 算法代码4.3 手动模拟4.4 算法特性4.5 相关例题5 简单选择排序5.1 算法简要思想5.2 算法特性6 堆排…

了解网络保险以及为什么它对您的业务很重要

本文&#xff0c;我们将探讨网络保险&#xff0c;它如何在发生网络攻击时帮助企业&#xff0c;以及为什么您的企业组织需要它。 大流行后的工作场所在很大程度上转向远程优先或混合安排&#xff0c;员工使用各种个人设备连接到公司网络。不良的网络卫生实践、缺乏足够的网络安全…

IDEA懒人必备插件:自动生成单元测试,太爽了!

今天&#xff0c;我们将介绍一个工具Squaretest&#xff0c;它是一个用于自动生成单元测试的插件。它也将被使用&#xff0c;因为该公司最近实施了代码质量控制指标&#xff0c;以评估各种项目的单元测试覆盖率和声纳扫描的各种问题。 许多旧项目和旧代码&#xff0c;或者需要匆…

ArcGIS基础:在线数据上生成规则采样点

需求&#xff1a;在线要素上等间距生成一定数量的采样点或者在线数据上随机生成一系列的采样点 原始数据如下所示&#xff0c;为一个普通的线数据&#xff0c;以下操作是在此线数据上生成一定数量的采样点。 注意&#xff1a;切记&#xff0c;点要素和线要素数据都要为shp格式…

飞桨生态之FastDeploy预编译库的使用方法

飞桨生态之FastDeploy预编译库的使用方法1 FastDeploy2 下载FastDeploy编译demo方法1 FastDeploy 为什么采用FastDeploy,由于之前使用PaddleOCR(paddlle_inference)框架的代码做推理&#xff0c;造成实际显存一直开辟&#xff0c;不释放我的问题&#xff0c;刚开始两个模型占用…

vxlan转发原理

openstack neutron组件也用到了vxlan&#xff0c;还有dvr&#xff0c;在云计算环境到底分布式网关好还是集中式网关好&#xff0c;vxlan对称还是非对称转发好&#xff0c;什么样的控制平面好&#xff0c;要对这些问题得出结论不管怎样先得深刻理解vxlan转发流程。 三层转发就是…

Java——继承——Extends

继承为什么要继承呢&#xff1f;继承的语法继承的概念子类中访问父类性质Java的单继承super和this子类构造方法protected中super的使用final关键字今天我们来说说面向对象的又一特征&#xff1a;继承&#xff01;为什么要继承呢&#xff1f; class Dog{public String name;pub…

QT Qmake 笔记

文章目录概述QT修改样式qmake概述库引用和库路径指定QT创建动态库和使用小例子写动态库用动态库参考资料附录概述 需要先安装osg&#xff0c;然后再编译安装osgQOpenGL的插件。 其中&#xff0c;osgQOpenGL是OSG嵌入到qt中的一种实现方式&#xff0c;换言之&#xff0c;能够支…

【小学信息技术教资面试】《认识鼠标》教案

1.题目&#xff1a;认识鼠标 2.内容&#xff1a; 3.基本要求&#xff1a; &#xff08;1&#xff09;掌握鼠标的基本操作 &#xff08;2&#xff09;体现学生的主体地位 &#xff08;3&#xff09;多种教学方法结合使用 &#xff08;4&#xff09;配合板书讲解 《认识鼠标》…