linux-cli-tools简易模拟开发

linux-cli-tools简易模拟开发

环境配置

系统环境:ubuntu20.04,gcc,g++,cmake //可以参考之前的环境搭建详解

工具:vscode(ssh),VMware,mobaxterm

简易描述

linux-cli-tools是一个简易的Linux命令行工具,其中对于基础命令进行简易的模拟及其实现,如 ls,grep,cat 等等。

目的是为了更好的了解Linux基础命令的原理及提高在Linux中进行开发C++项目。

目录框架

~/code/linux-cli-tools/

  • Makefile

~/code/linux-cli-tools/src/

  • my_ls.cpp -> ls
  • my_cat.cpp -> cat
  • my_cp.cpp -> cp
  • my_find.cpp -> find
  • my_grep.cpp -> grep
  • my_kill.cpp -> kill
  • my_ps.cpp -> ps
  • my_wc.cpp ->wc

实操流程:

为保证提高对Linux系统的熟练运用,该项目将在虚拟机开机后全程用vscode或mobaxterm中小黑盒进行命令操作。

建立目录

在前文所创建的目录(~/code)下创建该项目的整体目录文件框架

如图:

代码如下:

mkdir linux-cli-tools
cd linux-cli-tools
mkdir src
touch Makefile
cd src
touch my_ls.cpp my_cat.cpp my_cp.cpp my_find.cpp my_grep.cpp my_kill.cpp my_ps.cpp my_wc.cpp

编写程序

my_cat.cpp

#include<iostream>
#include<fstream>
#include<string>

void print_file(const std::string& filename)
{
    std:: ifstream file(filename);
    //创建一个文件流对象file(filename为该文件的路径及其名称)
    //判断能否打开
    if(!file.is_open())
    {
        std::cerr<<"Error: Unanle to open file"<<filename<<std::endl;
        return;
    }
    //如果成功打开那就getline 一行行输出
    std::string line;
    while(std::getline(file,line))
    {
        std::cout<<line<<std::endl;
    }
}

int main(int argc,char* argv[])
{
    if(argc<2)
    {
        std::cerr<<"Usage: "<<argv[0]<<"<filename>"<<std::endl;
        return 1;
    }

    print_file(argv[1]);
    return 0;
}

my_cp.cpp

#include <iostream>
#include <fstream>

void copy_file(const std::string& src, const std::string& dest) 
{
    std::ifstream src_file(src, std::ios::binary);
    if (!src_file) 
    {
        std::cerr << "Error: Unable to open source file " << src << std::endl;
        return;
    }

    std::ofstream dest_file(dest, std::ios::binary);
    if (!dest_file) 
    {
        std::cerr << "Error: Unable to open destination file " << dest << std::endl;
        return;
    }

    dest_file << src_file.rdbuf();
}

int main(int argc, char* argv[]) 
{
    if (argc < 3) {
        std::cerr << "Usage: " << argv[0] << " <source> <destination>" << std::endl;
        return 1;
    }

    copy_file(argv[1], argv[2]);
    return 0;
}

my_find.cpp

#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
#include <cstring>
#include <string>

void find_file(const std::string& dir, const std::string& target) 
{
    DIR* dp = opendir(dir.c_str());
    if (!dp) {
        std::cerr << "Error: Unable to open directory " << dir << std::endl;
        return;
    }

    struct dirent* entry;
    char path[1024];
    while ((entry = readdir(dp)) != nullptr) 
    {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;

        snprintf(path, sizeof(path), "%s/%s", dir.c_str(), entry->d_name);
        struct stat st;
        if (stat(path, &st) == 0 && S_ISDIR(st.st_mode)) 
        {
            find_file(path, target); 
        } else if (strstr(entry->d_name, target.c_str())) 
        {
            std::cout << path << std::endl;
        }
    }
    closedir(dp);
}

int main(int argc, char* argv[]) 
{
    //argc的作用是判断传入的参数是否足够
    if (argc < 3) 
    {
        std::cerr << "Usage: " << argv[0] << " <directory> <filename>" << std::endl;
        return 1;
    }
    find_file(argv[1], argv[2]);
    return 0;
}

my_grep.cpp

#include<iostream>
#include<fstream>
#include<regex>
#include<string>

void grep_file(const std::string& pattern,const std::string& filename)
{
    std::ifstream file(filename);
    if(!file.is_open())
    {
        std::cerr<<"Error:Unable to open file "<<filename<<std::endl;
        return;
    }
    std::regex regex(pattern);
    std::string line;
    while(std::getline(file,line))
    {
        if(std::regex_search(line,regex))
        {
            std::cout<<line<<std::endl;
        }
    }
}

int main(int argc,char* argv[])
{
    if(argc<3)
    {
        std::cerr<<"Usage: "<<argv[0]<<"<pattern> <filename> "<<std::endl;
        return 1;
    }

    grep_file(argv[1],argv[2]);
    return 0;
}

my_kill.cpp

#include <iostream>
#include <csignal>

void kill_process(int pid, int signal) 
{
    if (kill(pid, signal) == -1)
    {
        std::cerr << "Error: Unable to send signal to process " << pid << std::endl;
    }
    else 
    {
        std::cout << "Signal " << signal << " sent to process " << pid << std::endl;
    }
}

int main(int argc, char* argv[]) 
{
    if (argc < 3) 
    {
        std::cerr << "Usage: " << argv[0] << " <pid> <signal>" << std::endl;
        return 1;
    }

    int pid = std::stoi(argv[1]);
    int signal = std::stoi(argv[2]);
    kill_process(pid, signal);

    return 0;
}

my_ls.cpp

#include<iostream>
#include<dirent.h>
#include<sys/stat.h>
#include<cstring>

void list_directory(const std::string& path)
{
    DIR* dir = opendir(path.c_str());
    if(!dir)
    {
        std::cerr << "Error: Unable to open directory "<<path<<std::endl;
        return;
    }
    struct dirent* enrty;
    while((enrty = readdir(dir))!=nullptr)
    {
        std::cout<<enrty->d_name<<std::endl;
    }
    closedir(dir);
}
int main(int argc,char* argv[])
{
    if(argc<2)
    {
        list_directory(".");
    }
    else 
    {
        list_directory(argv[1]);
    }
    return 0;
}

my_ps.cpp

#include <iostream>
#include <dirent.h>
#include <sys/types.h>
#include <fstream>
#include <string>
#include <unistd.h>

// 获取进程的命令名称(即进程的执行文件)
std::string get_process_name(int pid) 
{
    std::string path = "/proc/" + std::to_string(pid) + "/comm";
    std::ifstream file(path);
    std::string process_name;

    if (file.is_open()) 
    {
        std::getline(file, process_name);  // 读取进程名
        file.close();
    }

    return process_name;
}

void my_ps() 
{
    DIR *dir = opendir("/proc");
    if (dir == nullptr) 
    {
        std::cerr << "Failed to open /proc directory." << std::endl;
        return;
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != nullptr) 
    {
        // 检查目录名是否为数字(即进程的 PID)
        if (entry->d_type == DT_DIR && std::isdigit(entry->d_name[0])) 
        {
            int pid = std::stoi(entry->d_name);  // 将 PID 转换为整数
            std::string process_name = get_process_name(pid);  // 获取进程名称
            std::cout << "PID: " << pid << " - " << process_name << std::endl;
        }
    }

    closedir(dir);
}

int main() 
{
    my_ps();  // 执行 my_ps 查看进程
    return 0;
}

my_wc.cpp

#include <iostream>
#include <fstream>
#include <string>

void count_file(const std::string& filename) 
{
    std::ifstream file(filename);
    if (!file.is_open()) 
    {
        std::cerr << "Error: Unable to open file " << filename << std::endl;
        return;
    }

    int lines = 0, words = 0, chars = 0;
    std::string word;
    while (file >> word) 
    {
        ++words;
    }

    file.clear(); // Clear EOF flag
    file.seekg(0); // Go back to the start of the file

    std::string line;
    while (std::getline(file, line)) 
    {
        ++lines;
        chars += line.size();
    }

    std::cout << "Lines: " << lines << ", Words: " << words << ", Characters: " << chars << std::endl;
}

int main(int argc, char* argv[]) 
{
    if (argc < 2) 
    {
        std::cerr << "Usage: " << argv[0] << " <filename>" << std::endl;
        return 1;
    }

    count_file(argv[1]);
    return 0;
}

Makefile

CXX = g++
CXXFLAGS = -std=c++11 -Wall

SRCDIR = src
SRC = $(wildcard $(SRCDIR)/*.cpp)
OBJ = $(SRC:.cpp=.o)

TARGETS = $(SRC:$(SRCDIR)/%.cpp=%)

all: $(TARGETS)

%: $(SRCDIR)/%.cpp
    $(CXX) $(CXXFLAGS) $< -o $@

clean:
    rm -rf $(OBJ) $(TARGETS)

.PHONY:clean

编译

打开终端(vscode或者mobaxtrem都行),到Makefile文本所在的目录

make

然后会生成相应的各个可执行文件。

测试

测试环节可以对应Linux中命令进行同等参数操作

例如

./my_cat ../Makefile

清除可执行文件

make clean

附加

简易制作可持续的进程

linux-cli-tools目录下创建demo.cpp

代码如下:

#include <iostream>
#include <unistd.h>  // 用于 fork()
#include <signal.h>  // 用于信号处理

// 子进程的工作函数
void child_process()
{
    int cnt = 1;
    while (true)
    {
        std::cout << "Child process is running..."<<cnt++<<" "<< std::endl;
        sleep(1);  // 每秒输出一次
    }
}

int main() {
    pid_t pid = fork();  // 创建子进程

    if (pid < 0) 
    {
        std::cerr << "Fork failed!" << std::endl;
        return 1;
    }

    if (pid == 0)
    {
        // 子进程代码
        child_process();
    } 
    else 
    {
        // 父进程代码
        std::cout << "Parent process created a child process with PID: " << pid << std::endl;
        // 父进程继续运行,可以做其他事情,或者等待子进程
        while (true) 
        {
            sleep(5);  // 父进程等待5秒
        }
    }

    return 0;
}

编译

终端执行

g++ demo.cpp -o demo

运行可执行文件demo

./demo

当前终端显示且继续增加

开启另一个终端进行

./my_kill 10701 9

则上一个终端停止运行但未退出

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇