最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Linux實(shí)現(xiàn)簡易版Shell的代碼詳解

 更新時(shí)間:2025年05月21日 11:33:44   作者:ephemerals__  
本篇文章,我們將一起踏上一段有趣的旅程,仿照CentOS?–?Bash的工作流程,實(shí)現(xiàn)一個(gè)功能雖然簡單,但足以讓你深刻理解?Shell?工作原理的迷你?Shell,g感興趣的小伙伴跟著小伙伴一起來看看吧

一、程序流程分析

我們?nèi)粘J褂肂ash時(shí),通過輸入命令執(zhí)行相應(yīng)的操作,比如:

在這里插入圖片描述

那么,Bash是如何進(jìn)行工作的呢?觀察一下,就會(huì)發(fā)現(xiàn),首先Bash會(huì)打印命令行提示符,包括當(dāng)前用戶、主機(jī)名以及路徑。之后會(huì)等待我們輸入相關(guān)命令,然后根據(jù)命令執(zhí)行相應(yīng)程序。程序執(zhí)行結(jié)束后,就會(huì)再次打印命令行提示符,等待我們?cè)俅屋斎胫噶?hellip;很明顯是一個(gè)死循環(huán)。

總結(jié)一下,Bash的大體工作流程是:

1.打印命令行提示符(包括當(dāng)前用戶名、主機(jī)名、路徑)
2.獲取用戶輸入的命令行
3.解析命令行
4.執(zhí)行命令
5.繼續(xù)打印命令行提示符…

注意:當(dāng)Bash執(zhí)行非內(nèi)建命令時(shí),會(huì)創(chuàng)建一個(gè)子進(jìn)程,由子進(jìn)程完成相應(yīng)的工作,Bash自己等待子進(jìn)程工作結(jié)束。而對(duì)于內(nèi)建命令(如cd,echo),需要Bash自己執(zhí)行任務(wù)。

![[Pasted image 20250518164821.png]]

二、代碼實(shí)現(xiàn)

接下來,我們開始按照上述工作流程,一步步實(shí)現(xiàn)我們的簡易Shell。

1. 打印命令行提示符

CentOS的命令行提示符主要包含三個(gè)內(nèi)容:當(dāng)前用戶名、主機(jī)名和當(dāng)前所在路徑。 之前學(xué)習(xí)Linux環(huán)境變量時(shí),我們了解到環(huán)境變量(USER、HOSTNAME、PWD)中存儲(chǔ)著這些內(nèi)容。所以我們使用getenv函數(shù)獲取環(huán)境變量相應(yīng)的值。

代碼實(shí)現(xiàn):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

//獲取當(dāng)前用戶名
const char* GetUserName()
{
    const char* name = getenv("USER");
    return name == nullptr ? "none" : name;
}

//獲取當(dāng)前主機(jī)名
const char* GetHostName()
{
    const char* name = getenv("HOSTNAME");
    return name == nullptr ? "none" : name;
}

//獲取當(dāng)前工作路徑
const char* GetPwd()
{
    const char* pwd = getenv("PWD");
    return pwd == nullptr ? "none" : pwd;
}

接下來,調(diào)用這些函數(shù),形成一串命令行提示符并打印:

//創(chuàng)建并打印命令行提示符
void PrintCommandPrompt()
{
    char CommandPrompt[1024];
    //這里為了區(qū)分Bash,用大括號(hào)
    snprintf(CommandPrompt, sizeof CommandPrompt,"{%s@%s %s}@ " , GetUserName(), GetHostName(), GetPwd());
    std::cout << CommandPrompt << std::flush; // 打印并刷新緩沖區(qū)
}

注意這里打印結(jié)束后,由于沒有換行,所以緩沖區(qū)可能不會(huì)刷新,導(dǎo)致命令行提示符沒有出現(xiàn)在屏幕上。因此這里我們需要主動(dòng)刷新緩沖區(qū)。

進(jìn)行測試:

int main()
{
    PrintCommandPrompt();
    return 0;
}

運(yùn)行結(jié)果:

obsidian://open?vault=%E5%8D%9A%E5%AE%A2&file=Pasted%20image%2020250518155420.png

可以看到,用戶名和主機(jī)名都正常打印,但在我們寫的shell中,當(dāng)前所在路徑是絕對(duì)路徑,太過冗長,所以可以對(duì)生成的路徑進(jìn)行一些處理:

//創(chuàng)建并打印命令行提示符
void PrintCommandPrompt()
{
    char CommandPrompt[1024];
    
    //處理當(dāng)前工作路徑
    std::string pwd = GetPwd();
    if(pwd != "/") // 如果是根目錄,則直接輸出
        pwd = pwd.substr(pwd.rfind('/') + 1); // 查找最后一個(gè)"/",并從下一個(gè)位置開始分割

    //這里為了區(qū)分Bash,用大括號(hào)
    snprintf(CommandPrompt, sizeof CommandPrompt,"{%s@%s %s}@ " , GetUserName(), GetHostName(), pwd.c_str());
    std::cout << CommandPrompt << std::flush; // 打印并刷新緩沖區(qū)
}

運(yùn)行結(jié)果:

![[Pasted image 20250518161526.png]]

2. 獲取用戶輸入的命令行

在Bash輸入命令時(shí),往往會(huì)帶上一些選項(xiàng),并用空格隔開。因此,使用scanf或cin讀入時(shí)會(huì)以空格作為分隔符,達(dá)不到想要的效果。這里我們選擇用fgets進(jìn)行讀取。

另外,主函數(shù)當(dāng)中,命令的全部處理應(yīng)該放在一個(gè)死循環(huán)當(dāng)中,這樣才能完成用戶多次派發(fā)的任務(wù)。

//獲取用戶輸入的命令行
bool GetCommandLine(char* command, int size)
{
    //從鍵盤讀取命令
    if(fgets(command, size, stdin) == nullptr)
    {
        return false;
    }

    //注意清理末尾的'\n'
    if(strlen(command) == 0) return false;
    command[strlen(command) - 1] = '\0';
    return true;
}

int main()
{
    while(true)
    {
        //打印命令行提示符
        PrintCommandPrompt();

        //讀入命令
        char command[1024];
        if(!GetCommandLine(command, sizeof command)) // 若讀取錯(cuò)誤,就continue重新讀取
        {
            std::cout << "讀取錯(cuò)誤" << std::endl;
            continue;
        }

        //打印輸入的命令行
        std::cout << command << std::endl;
    }
    return 0;
}

注意:使用fgets從鍵盤讀取字符串時(shí)會(huì)附帶末尾’\n’,需要進(jìn)行處理。

運(yùn)行測試:

![[Pasted image 20250518165317.png]]

可以看到,程序成功讀入了我們的命令(包括空格),并且將命令回顯出來。

3. 命令行解析

命令行解析的過程中,需要將用戶讀入的命令行進(jìn)行分割,提取出要執(zhí)行的程序名以及選項(xiàng)。這里我們創(chuàng)建兩個(gè)全局變量g_argc和g_argv,分別存儲(chǔ)解析到的命令行參數(shù)以及參數(shù)個(gè)數(shù),方便后續(xù)指令的執(zhí)行。

注:這里的命令行分割操作由strtok函數(shù)完成。

代碼實(shí)現(xiàn):

//全局變量存儲(chǔ)命令行參數(shù)及其個(gè)數(shù)
int g_argc = 0;
char* g_argv[128];

//命令行解析
bool CommandParse(char* command)
{
    g_argc = 0;
    for(char* p = strtok(command, " "); p != nullptr; p = strtok(nullptr, " "))
    {
        g_argv[g_argc++] = p;
    }
    return g_argc == 0 ? false : true;
}

int main()
{
    while(true)
    {
        //打印命令行提示符
        PrintCommandPrompt();

        //讀入命令
        char command[1024];
        if(!GetCommandLine(command, sizeof command)) // 若讀取錯(cuò)誤,就continue重新讀取
        {
            std::cout << "輸入錯(cuò)誤" << std::endl;
            continue;
        }
        // //打印輸入的命令行
        // std::cout << command << std::endl;

        //命令行解析
        if(!CommandParse(command))
        {
            std::cout << "命令行解析失敗" << std::endl;
            continue;
        }
        //打印解析結(jié)果
        for(int i = 0; i < g_argc; i++)
        {
            std::cout << g_argv[i] << std::endl;
        }
    }
    return 0;
}

測試結(jié)果:

![[Pasted image 20250518173801.png]]

程序成功地按照空格將我們輸入的命令行參數(shù)提取了出來。接下來,根據(jù)提取到的參數(shù),就可以執(zhí)行相關(guān)指令了。

4. 執(zhí)行命令

對(duì)于非內(nèi)建命令,Bash會(huì)創(chuàng)建子進(jìn)程,并讓子進(jìn)程執(zhí)行;而對(duì)于內(nèi)建命令,則是由Bash自己執(zhí)行。因此,執(zhí)行命令之前,需要先判斷該命令是否是內(nèi)建命令,然后進(jìn)行相應(yīng)的操作。

為什么會(huì)有內(nèi)建命令?

  • 效率: 執(zhí)行內(nèi)建命令通常比執(zhí)行外部命令更快,因?yàn)楸苊饬藙?chuàng)建新進(jìn)程的開銷。
  • Shell 功能: 許多內(nèi)建命令直接操作 Shell 的內(nèi)部狀態(tài),例如改變當(dāng)前工作目錄 (cd)、設(shè)置環(huán)境變量 (export)、控制 Shell 行為等,這些功能如果作為外部命令實(shí)現(xiàn)會(huì)更加復(fù)雜或不可能。
  • 基本操作: 一些非常基礎(chǔ)和常用的操作需要作為內(nèi)建命令提供,以確保 Shell 的基本功能可用

內(nèi)建命令的處理

在Bash當(dāng)中,可以使用type命令判斷一個(gè)命令是否是內(nèi)建命令,例如:

![[Pasted image 20250518174929.png]]

當(dāng)然,除了cd和echo命令,還有printf、help等內(nèi)建命令。本次實(shí)現(xiàn)中,為了能夠讓大家深刻理解shell運(yùn)行原理,同時(shí)降低實(shí)現(xiàn)難度,博主就只針對(duì)cd和echo這兩個(gè)內(nèi)建命令進(jìn)行簡易實(shí)現(xiàn)。

內(nèi)建命令的檢查和處理:

//內(nèi)建命令處理
bool CheckAndExecBuiltin()
{
    //取出命令行參數(shù)表的首元素,判斷是否為內(nèi)建命令,如果是,則直接執(zhí)行
    std::string str = g_argv[0];
    if(str == "cd")
    {
        Cd();
        return true;
    }
    else if(str == "echo")
    {
        Echo();
        return true;
    }
    //else if(...)
    return false; // 不是內(nèi)建命令,直接返回
}

int main()
{
    while(true)
    {
        //打印命令行提示符
        PrintCommandPrompt();

        //讀入命令
        char command[1024];
        if(!GetCommandLine(command, sizeof command)) // 若讀取錯(cuò)誤,就continue重新讀取
        {
            std::cout << "輸入錯(cuò)誤" << std::endl;
            continue;
        }
        // //打印輸入的命令行
        // std::cout << command << std::endl;

        //命令行解析
        if(!CommandParse(command))
        {
            std::cout << "命令行解析失敗" << std::endl;
            continue;
        }
        // //打印解析結(jié)果
        // for(int i = 0; i < g_argc; i++)
        // {
        //     std::cout << g_argv[i] << std::endl;
        // }

        //內(nèi)建命令的處理
        if(CheckAndExecBuiltin())
        {
            continue; // 是內(nèi)建命令,執(zhí)行完畢就回去重新打印提示符
        }

        //不是內(nèi)建命令,由子進(jìn)程處理
    }
    return 0;
}

cd的簡易實(shí)現(xiàn)

cd的功能是改變當(dāng)前工作路徑。如果創(chuàng)建子進(jìn)程,其只能修改它自己的工作路徑,而無法修改Bash的工作路徑。因此cd操作需要Bash親自完成。 我們獲取到命令行參數(shù)后,可以通過調(diào)用chdir函數(shù)實(shí)現(xiàn):

void Cd()
{
    std::string dst;
    if(g_argc == 1 || g_argv[1] == std::string("~")) // 處理進(jìn)入家目錄的情況
    {
        dst = GetHome();
        if(dst == "") return;
    }
    else
    {
        dst = g_argv[1];
    }
    chdir(dst.c_str());
}

測試結(jié)果:

![[Pasted image 20250518190207.png]]

可以看到,使用cd后,當(dāng)前路徑貌似并沒有發(fā)生改變。為什么呢?實(shí)際上chdir確實(shí)起到了效果,但是我們的命令行提示符中,當(dāng)前工作路徑是從環(huán)境變量中獲取的,環(huán)境變量中的PWD并沒有發(fā)生改變。 因此,修改當(dāng)前工作路徑之后,要順帶著修改環(huán)境變量PWD的值。其次,當(dāng)前工作路徑改變后,修改環(huán)境變量之前,要獲取到當(dāng)前工作路徑,就需要使用getcwd函數(shù)。進(jìn)行鍵值處理后,使用putenv修改環(huán)境變量。

另外要注意:許多putenv函數(shù)的實(shí)現(xiàn)(特別是 POSIX 標(biāo)準(zhǔn)的實(shí)現(xiàn))不會(huì)復(fù)制我們傳遞給它的字符串,而會(huì)直接使用傳入的指針來表示新的環(huán)境變量,因此要?jiǎng)?chuàng)建一個(gè)全局變量存儲(chǔ)PWD鍵值對(duì),確保其不會(huì)被銷毀。

![[Pasted image 20250518193953.png]]

代碼實(shí)現(xiàn):

//全局的當(dāng)前工作路徑
char cwd[256];

void Cd()
{
    std::string dst;
    if(g_argc == 1 || g_argv[1] == "~") // 處理進(jìn)入家目錄的情況
    {
        dst = GetHome();
        if(dst == "") return;
    }
    else
    {
        dst = g_argv[1];
    }
    chdir(dst.c_str());

    //同時(shí)修改環(huán)境變量中的當(dāng)前工作路徑
    char tmp[128];
    if(getcwd(tmp, sizeof tmp))
    {
        snprintf(cwd, sizeof cwd, "PWD=%s", tmp); // 鍵值處理
        putenv(cwd);
    }
}

測試結(jié)果:

![[Pasted image 20250518200749.png]]

echo的簡易實(shí)現(xiàn)

echo不僅可以向屏幕打印字符串,還可以打印上一個(gè)執(zhí)行的程序的退出碼、以及環(huán)境變量等信息。為了確保效率以及執(zhí)行的可靠性,該命令也是一個(gè)內(nèi)建命令,由Bash親自執(zhí)行。

//全局變量記錄上一個(gè)程序的退出碼
int exit_code;

void Echo()
{
    std::string op = g_argv[1];
    if(op == "$?") // 打印上一個(gè)程序的退出碼
    {
        std::cout << exit_code << std::endl;
        exit_code = 0;
    }
    else if(op[0] == '$') // 打印環(huán)境變量的值
    {
        //從"$"后的第一個(gè)字符開始,獲取環(huán)境變量名
        std::string name = op.substr(1);

        //用getenv獲取環(huán)境變量值
        const char* value = getenv(name.c_str());
        if(value)
            std::cout << value << std::endl;
    }
    else // 打印字符串
    {
        std::cout << op << std::endl;
    }
}

測試結(jié)果:

![[Pasted image 20250518200451.png]]

非內(nèi)建命令的處理

針對(duì)非內(nèi)建命令,需要?jiǎng)?chuàng)建子進(jìn)程,然后由子進(jìn)程找到系統(tǒng)的對(duì)應(yīng)指令程序的位置,直接進(jìn)行進(jìn)程程序替換,完成相關(guān)任務(wù)。這樣我們就無需一個(gè)個(gè)實(shí)現(xiàn)相關(guān)指令操作了。

為了讓子進(jìn)程自動(dòng)查找對(duì)應(yīng)程序的位置,減少我們的工作量,且使程序替換的參數(shù)與我們創(chuàng)建的全局命令行參數(shù)表一一對(duì)應(yīng),這里我們直接選用execvp進(jìn)行程序替換。

#include <unistd.h>
  
int execvp(const char *file, char *const argv[])

代碼實(shí)現(xiàn):

//執(zhí)行非內(nèi)建命令
void Execute()
{
    //創(chuàng)建子進(jìn)程
    pid_t id = fork();
    if(id < 0)
    {
        //創(chuàng)建子進(jìn)程失敗,直接退出
        exit(1);
    }
    else if(id == 0)
    {
        //子進(jìn)程 -- 通過程序替換執(zhí)行指令
        execvp(g_argv[0], g_argv);
    }
    else
    {
        //父進(jìn)程 -- 等待子進(jìn)程,并獲取子進(jìn)程的退出信息
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid > 0) // 等待成功
        {
            //將退出信息存入全局exit_code
            exit_code = WEXITSTATUS(status);
        }
    }
}

int main()
{
    while(true)
    {
        //打印命令行提示符
        PrintCommandPrompt();

        //讀入命令
        char command[1024];
        if(!GetCommandLine(command, sizeof command)) // 若讀取錯(cuò)誤,就continue重新讀取
        {
            std::cout << "輸入錯(cuò)誤" << std::endl;
            continue;
        }
        // //打印輸入的命令行
        // std::cout << command << std::endl;

        //命令行解析
        if(!CommandParse(command))
        {
            std::cout << "命令行解析失敗" << std::endl;
            continue;
        }
        // //打印解析結(jié)果
        // for(int i = 0; i < g_argc; i++)
        // {
        //     std::cout << g_argv[i] << std::endl;
        // }

        //內(nèi)建命令的處理
        if(CheckAndExecBuiltin())
        {
            continue; // 是內(nèi)建命令,執(zhí)行完畢就回去重新打印提示符
        }

        //不是內(nèi)建命令,由子進(jìn)程處理
        Execute();
    }
    return 0;
}

三、測試

接下來,我們輸入一些指令進(jìn)行測試,看看我們實(shí)現(xiàn)的shell能否達(dá)到預(yù)期效果:

![[Pasted image 20250518203838.png]]

perfect!

四、程序全部代碼

自實(shí)現(xiàn)shell的全部代碼如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

//全局變量存儲(chǔ)命令行參數(shù)及其個(gè)數(shù)
int g_argc = 0;
char* g_argv[128];

//全局的當(dāng)前工作路徑
char cwd[256];

//全局變量記錄上一個(gè)程序的退出碼
int exit_code;

//獲取當(dāng)前用戶名
const char* GetUserName()
{
    const char* name = getenv("USER");
    return name == nullptr ? "none" : name;
}

//獲取當(dāng)前主機(jī)名
const char* GetHostName()
{
    const char* name = getenv("HOSTNAME");
    return name == nullptr ? "none" : name;
}

//獲取當(dāng)前工作路徑
const char* GetPwd()
{
    const char* pwd = getenv("PWD");
    return pwd == nullptr ? "none" : pwd;
}

//獲取用戶的家目錄
const char* GetHome()
{
    const char* home = getenv("HOME");
    return home == nullptr ? "" : home;
}

//創(chuàng)建并打印命令行提示符
void PrintCommandPrompt()
{
    char CommandPrompt[1024];
    
    //處理當(dāng)前工作路徑
    std::string pwd = GetPwd();
    if(pwd != "/") // 如果是根目錄,則直接輸出
        pwd = pwd.substr(pwd.rfind('/') + 1); // 查找最后一個(gè)"/",并從下一個(gè)位置開始分割

    //這里為了區(qū)分Bash,用大括號(hào)
    snprintf(CommandPrompt, sizeof CommandPrompt,"{%s@%s %s}@ " , GetUserName(), GetHostName(), pwd.c_str());
    std::cout << CommandPrompt << std::flush; // 打印并刷新緩沖區(qū)
}

//獲取用戶輸入的命令行
bool GetCommandLine(char* command, int size)
{
    //從鍵盤讀取命令
    if(fgets(command, size, stdin) == nullptr)
    {
        return false;
    }

    //注意清理末尾的'\n'
    if(strlen(command) == 0) return false;
    command[strlen(command) - 1] = '\0';
    return true;
}

//命令行解析
bool CommandParse(char* command)
{
    g_argc = 0;
    for(char* p = strtok(command, " "); p != nullptr; p = strtok(nullptr, " "))
    {
        g_argv[g_argc++] = p;
    }
    return g_argc == 0 ? false : true;
}

void Cd()
{
    std::string dst;
    if(g_argc == 1 || g_argv[1] == std::string("~")) // 處理進(jìn)入家目錄的情況
    {
        dst = GetHome();
        if(dst == "") return;
    }
    else
    {
        dst = g_argv[1];
    }
    chdir(dst.c_str());

    //同時(shí)修改環(huán)境變量中的當(dāng)前工作路徑
    char tmp[128];
    if(getcwd(tmp, sizeof tmp))
    {
        snprintf(cwd, sizeof cwd, "PWD=%s", tmp);
        putenv(cwd);
    }
}

void Echo()
{
    std::string op = g_argv[1];
    if(op == "$?") // 打印上一個(gè)程序的退出碼
    {
        std::cout << exit_code << std::endl;
        exit_code = 0;
    }
    else if(op[0] == '$') // 打印環(huán)境變量的值
    {
        //從"$"后的第一個(gè)字符開始,獲取環(huán)境變量名
        std::string name = op.substr(1);

        //用getenv獲取環(huán)境變量值
        const char* value = getenv(name.c_str());
        if(value)
            std::cout << value << std::endl;
    }
    else // 打印字符串
    {
        std::cout << op << std::endl;
    }
}

//內(nèi)建命令處理
bool CheckAndExecBuiltin()
{
    //取出命令行參數(shù)表的首元素,判斷是否為內(nèi)建命令,如果是,則直接執(zhí)行
    std::string str = g_argv[0];
    if(str == "cd")
    {
        Cd();
        return true;
    }
    else if(str == "echo")
    {
        Echo();
        return true;
    }
    //else if(...)
    return false; // 不是內(nèi)建命令,直接返回
}

//執(zhí)行非內(nèi)建命令
void Execute()
{
    //創(chuàng)建子進(jìn)程
    pid_t id = fork();
    if(id < 0)
    {
        //創(chuàng)建子進(jìn)程失敗,直接退出
        exit(1);
    }
    else if(id == 0)
    {
        //子進(jìn)程 -- 通過程序替換執(zhí)行指令
        execvp(g_argv[0], g_argv);
    }
    else
    {
        //父進(jìn)程 -- 等待子進(jìn)程,并獲取子進(jìn)程的退出信息
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        if(rid > 0) // 等待成功
        {
            //將退出信息存入全局exit_code
            exit_code = WEXITSTATUS(status);
        }
    }
}

int main()
{
    while(true)
    {
        //打印命令行提示符
        PrintCommandPrompt();

        //讀入命令
        char command[1024];
        if(!GetCommandLine(command, sizeof command)) // 若讀取錯(cuò)誤,就continue重新讀取
        {
            std::cout << "輸入錯(cuò)誤" << std::endl;
            continue;
        }
        // //打印輸入的命令行
        // std::cout << command << std::endl;

        //命令行解析
        if(!CommandParse(command))
        {
            std::cout << "命令行解析失敗" << std::endl;
            continue;
        }
        // //打印解析結(jié)果
        // for(int i = 0; i < g_argc; i++)
        // {
        //     std::cout << g_argv[i] << std::endl;
        // }

        //內(nèi)建命令的處理
        if(CheckAndExecBuiltin())
        {
            continue; // 是內(nèi)建命令,執(zhí)行完畢就回去重新打印提示符
        }

        //不是內(nèi)建命令,由子進(jìn)程處理
        Execute();
    }
    return 0;
}

總結(jié)

本篇文章,我們基于之前學(xué)習(xí)的Linux進(jìn)程相關(guān)概念以及進(jìn)程控制接口,實(shí)現(xiàn)了一個(gè)簡易版的shell。本次實(shí)現(xiàn)讓我們對(duì)Shell的運(yùn)行原理有了更深刻的理解。

以上就是Linux實(shí)現(xiàn)簡易版Shell的代碼詳解的詳細(xì)內(nèi)容,更多關(guān)于Linux簡易版Shell的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 每天一個(gè)linux命令 whereis命令

    每天一個(gè)linux命令 whereis命令

    這篇文章主要為大家詳細(xì)介紹了一個(gè)linux命令:whereis命令,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • linux的cut命令用法總結(jié)

    linux的cut命令用法總結(jié)

    今天小編就為大家分享一篇關(guān)于linux的cut命令用法總結(jié),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • SHELL中pr命令的實(shí)現(xiàn)

    SHELL中pr命令的實(shí)現(xiàn)

    pr是 “print” 的縮寫,主要用于將文本文件分頁,并添加頁眉、頁碼等信息,本文就來詳細(xì)的介紹一下SHELL中pr命令的實(shí)現(xiàn),感興趣的可以了解一下
    2025-09-09
  • shell腳本結(jié)合Linux命令實(shí)現(xiàn)批量創(chuàng)建用戶并生成隨機(jī)密碼

    shell腳本結(jié)合Linux命令實(shí)現(xiàn)批量創(chuàng)建用戶并生成隨機(jī)密碼

    在日常 Linux 運(yùn)維或測試環(huán)境中,經(jīng)常會(huì)遇到需要批量創(chuàng)建用戶并設(shè)置密碼的場景,下面我們就來看看如何 使用 Bash 腳本 + Linux 命令 批量創(chuàng)建 100 個(gè)用戶,并將用戶名和密碼保存到文本文件中吧
    2025-12-12
  • shell腳本使用兩個(gè)橫杠接收外部參數(shù)的方法

    shell腳本使用兩個(gè)橫杠接收外部參數(shù)的方法

    這篇文章主要介紹了shell腳本使用兩個(gè)橫杠接收外部參數(shù)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • shell如何記錄用戶的IP與命令詳解

    shell如何記錄用戶的IP與命令詳解

    這篇文章主要給大家介紹了關(guān)于shell是如何記錄用戶的IP與命令的相關(guān)資料,記錄用戶輸入過的命令使用history命令,而記錄用戶的IP可能稍復(fù)雜一些,需要的朋友們下面跟著小編一起來看看吧。
    2017-06-06
  • 淺析Shell腳本中的條件判斷[?]與[[?]]的區(qū)別

    淺析Shell腳本中的條件判斷[?]與[[?]]的區(qū)別

    在編寫?Shell?腳本時(shí),條件判斷是控制腳本流程的重要手段,Shell?提供了多種方式來進(jìn)行條件判斷,其中[?]和[[?]]是兩種常見的條件測試表達(dá)式,下面我們就來看看兩者的區(qū)別吧
    2024-12-12
  • linux 創(chuàng)建守護(hù)進(jìn)程的相關(guān)知識(shí)

    linux 創(chuàng)建守護(hù)進(jìn)程的相關(guān)知識(shí)

    這篇文章主要介紹了linux 創(chuàng)建守護(hù)進(jìn)程的相關(guān)知識(shí),需要的朋友可以參考下
    2014-01-01
  • Linux系統(tǒng)診斷之內(nèi)存基礎(chǔ)深入詳解

    Linux系統(tǒng)診斷之內(nèi)存基礎(chǔ)深入詳解

    這篇文章主要介紹了Linux系統(tǒng)診斷之內(nèi)存基礎(chǔ)深入詳解,雖然是基礎(chǔ)但是列舉的很詳細(xì),有感興趣的同學(xué)可以研究下
    2021-03-03
  • 一個(gè)簡單的linux命令 cat

    一個(gè)簡單的linux命令 cat

    這篇文章主要介紹了一個(gè)簡單的linux命令cat,cat命令用來顯示文件內(nèi)容,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-12-12

最新評(píng)論

沧州市| 大连市| 安龙县| 阿拉善右旗| 兴城市| 拜城县| 永安市| 柳河县| 托里县| 砀山县| 拜城县| 洪湖市| 陵川县| 和龙市| 镇安县| 珠海市| 永吉县| 柏乡县| 翁源县| 谢通门县| 廉江市| 云霄县| 怀仁县| 莱西市| 华坪县| 上栗县| 清新县| 河北区| 定陶县| 洪雅县| 宝清县| 秭归县| 南平市| 泰州市| 庐江县| 淳安县| 和政县| 岚皋县| 麻阳| 色达县| 枞阳县|