国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【看表情包學(xué)Linux】插敘:實(shí)現(xiàn)簡(jiǎn)易的 Shell | 通過內(nèi)建命令實(shí)現(xiàn)路徑切換 | 再次理解環(huán)境變量

這篇具有很好參考價(jià)值的文章主要介紹了【看表情包學(xué)Linux】插敘:實(shí)現(xiàn)簡(jiǎn)易的 Shell | 通過內(nèi)建命令實(shí)現(xiàn)路徑切換 | 再次理解環(huán)境變量。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維???爆笑教程????《看表情包學(xué)Linux》???猛戳訂閱????

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

?? 寫在前面:本章是個(gè) "插敘",前幾章我們學(xué)了程序替換,現(xiàn)在我們可以嘗試動(dòng)手做一個(gè) "會(huì)創(chuàng)建,會(huì)終止,會(huì)等待,會(huì)程序替換" 的簡(jiǎn)易?shell 了。通過本章的內(nèi)容,可以進(jìn)一步鞏固進(jìn)程替換,學(xué)習(xí)內(nèi)建命令的概念以實(shí)現(xiàn)路徑切換,并再次理解環(huán)境變量。

?? 本章目錄:

0x00 補(bǔ)充:Vim 小技巧之文本替換

0x01 顯示提示符和獲取用戶輸入

0x02 將接收到的字符串拆開

0x03 創(chuàng)建進(jìn)程 & 程序替換

0x04 給命令帶顏色

0x05?內(nèi)建命令:實(shí)現(xiàn)路徑切換

0x06 再次理解環(huán)境變量

?如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維? 本篇博客全站熱榜排名:未上榜?


0x00 補(bǔ)充:Vim 小技巧之文本替換

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?在開始之前,我們先補(bǔ)充一個(gè)??使用小技巧:?:%s///g

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

0x01 顯示提示符和獲取用戶輸入

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?shell 本質(zhì)就是個(gè)死循環(huán),我們不關(guān)心獲取這些屬性的接口,如果要實(shí)現(xiàn) shell:

  • Step1:顯示提示符 →??#
  • Step2:獲取用戶輸入 → fgets
  • Step3:將接收到的字符串拆開? →??把 "ls -a -l"?轉(zhuǎn)換成??"ls"? "-a"? "-l"?
  • ……

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?我們先從簡(jiǎn)單的入手,先來實(shí)現(xiàn)前兩步,顯示提示符 獲取用戶輸入

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#define NUM 1024

char command_line[NUM];   // 用來接收命令行內(nèi)容

int main(void)
{
    while (1) {
        /* Step1:顯示提示符 */
        printf("[檸檬葉子@我的主機(jī)名 當(dāng)前目錄] # ");
        fflush(stdout);

        /* Step2:獲取用戶輸入 */
        memset (
            command_line, 
            '\0', 
            sizeof(command_line) * sizeof(char)
        );
        fgets(command_line, NUM, stdin);  /* 從鍵盤獲取,標(biāo)準(zhǔn)輸入,stdin 
            獲取到 C 風(fēng)格的字符串,默認(rèn)添加 '\0' */
        printf("%s\n", command_line);
    }
}

?? 說明:我們利用 fgets 函數(shù)從鍵盤上獲取,標(biāo)準(zhǔn)輸入?stdin,獲取到 C 風(fēng)格的字符串,

注意默認(rèn)會(huì)添加 \0?,我們先把獲取到的結(jié)果 command_line 打印出來看看:

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?因?yàn)?command_line 里有一個(gè) \n,我們把它替換成 \0 即可:

 command_line[strlen(command_line) - 1] = '\0';  // 消除 '\0'

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

至此,我們已經(jīng)完成了提示用戶輸入,并且也獲取到用戶的輸入了。

0x02 將接收到的字符串拆開

下面我們需要 將接收到的字符串拆開,比如:把 "ls -a -l" 拆成??"ls"? "-a"? "-l"?

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?因?yàn)?exec 函數(shù)簇?zé)o論是列表傳參還是數(shù)組傳參,一定是要逐個(gè)傳遞的!

"所以我們不得不拆,我的四十米長(zhǎng)刀早已饑渴難耐!"

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?我們可以使用 strtok 函數(shù),將一個(gè)字符串按照特定的分隔符打散,將子串依次返回:

char* strtok(char* str, const char* delim);

?? 代碼演示:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#define NUM 1024
#define SEP " "

char command_line[NUM];     // 存儲(chǔ)命令行內(nèi)容
char* command_args[SIZE];   // 命令參數(shù)

int main(void)
{
    while (1) {
        /* Step1:顯示提示符 */
        printf("[檸檬葉子@我的主機(jī)名 當(dāng)前目錄] # ");
        fflush(stdout);

        /* Step2:獲取用戶輸入 */
        memset (
            command_line, 
            '\0', 
            sizeof(command_line) * sizeof(char)
        );
        fgets(command_line, NUM, stdin);  /* 從鍵盤獲取,標(biāo)準(zhǔn)輸入,stdin 
            獲取到 C 風(fēng)格的字符串,默認(rèn)添加 '\0' */
        command_line[strlen(command_line) - 1] = '\0';  // 消除 '\0'

        /* Step3: 將接收到的字符串拆開 - 字符串切分 */
        command_args[0] = strtok(command_line, SEP);    // 按空格切分
        int idx = 1;
        /* 這里的 = 是故意這么寫的,因?yàn)?strtok 截取成功返回字符串起始地址
            截取失敗,返回 NULL */
        while (command_args[idx++] = strtok(NULL, SEP));

        // 我們來測(cè)試一下看看 
        for (int i = 0; i < idx; i++) {
            printf("%d : %s\n", command_args[i]);
        }

        printf("%s\n", command_line);
    }
}

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

字符串切分搞定了!

0x03 創(chuàng)建進(jìn)程 & 程序替換

下面我們實(shí)現(xiàn) 創(chuàng)建進(jìn)程,執(zhí)行它。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>

#define NUM 1024
#define SEP " "
#define SIZE 128

char command_line[NUM];
char* command_args[SIZE];

int main(void)
{
    while (1) {
        /* Step1:顯示提示符 */
        printf("[檸檬葉子@我的主機(jī)名 當(dāng)前目錄] # ");
        fflush(stdout);

        /* Step2:獲取用戶輸入 */
        memset (
            command_line, 
            '\0', 
            sizeof(command_line) * sizeof(char)
        );
        fgets(command_line, NUM, stdin);  /* 從鍵盤獲取,標(biāo)準(zhǔn)輸入,stdin 
            獲取到 C 風(fēng)格的字符串,默認(rèn)添加 '\0' */
        command_line[strlen(command_line) - 1] = '\0';  // 消除 '\0'

        /* Step3: 將接收到的字符串拆開 - 字符串切分 */
        command_args[0] = strtok(command_line, SEP);
        int idx = 1;
        
        /* 這里的 = 是故意這么寫的,因?yàn)?strtok 截取成功返回字符串起始地址
            截取失敗,返回 NULL */
        while (command_args[idx++] = strtok(NULL, SEP));

        //我們來測(cè)試一下看看 
        // for (int i = 0; i < idx; i++) {
        //     printf("%d : %s\n", i, command_args[i]);
        // }

        // printf("%s\n", command_line);

        /* Step4. TODO */
        /* Step5. 創(chuàng)建進(jìn)程,執(zhí)行 */
        pid_t id = fork();
        if (id == 0) {
            /* child */
            /* Step6: 程序替換 */
            execvp (
                command_args[0],  // 保存的是我們要執(zhí)行的程序名字
                command_args
            );

            exit(1);   // 只要執(zhí)行到這里,子進(jìn)程一定是替換失敗了,直接退出。
        }

        /* Father */
        int status = 0;
        pid_t ret = waitpid(id, &status, 0);
        if (ret > 0) {   // 等待成功
            printf("等待成功!sig: %d, code: %d\n", status&0x7F, (status>>8)&0xFF);
        }
    } // end while

}

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

0x04 給命令帶顏色

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?還有很多地方不完美,比如:如何讓我們的命令帶顏色呢?

?? 代碼演示:給 ls 命令添加顏色

        /* Step3: 將接收到的字符串拆開 - 字符串切分 */
        command_args[0] = strtok(command_line, SEP);
        int idx = 1;

        // 顏色的添加 -> 提出程序名,如果名師輸入 ls,在 command 里添加 --color
        if (strcmp(command_args[0] /* 程序名 */, "ls") == 0) {
            command_args[idx++] = (char*)"--color=auto";
        }

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

0x05?內(nèi)建命令:實(shí)現(xiàn)路徑切換

目前還有一個(gè)問題,我們 cd..?回退到上級(jí)目錄時(shí),我們的路徑是不發(fā)生變化的:

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

真相:雖然系統(tǒng)中存在 cd 命令,但我們寫的 shell 腳本中用的根本就不是這個(gè) cd 命令。

當(dāng)你在執(zhí)行 cd 命令時(shí),調(diào)用 execvp 執(zhí)行的實(shí)際上是系統(tǒng)特定路徑下的 cd:

        if (id == 0) {
            /* child */
            /* Step6: 程序替換 */
            execvp (
                command_args[0],  // 保存的是我們要執(zhí)行的程序名字
                command_args
            );

            exit(1);   // 只要執(zhí)行到這里,子進(jìn)程一定是替換失敗了,直接退出。
        }

它只影響了子進(jìn)程,如果我們直接 exec* 執(zhí)行 cd,那么最多只是讓子進(jìn)程進(jìn)行路徑切換。

但是請(qǐng)不要忘了:子進(jìn)程是一運(yùn)行就完畢的進(jìn)程!運(yùn)行完了你切換它的路徑,毫無意義。

所以,我們?cè)?shell 中,更希望誰的路徑發(fā)生變化呢?父進(jìn)程?。╯hell 本身)

父進(jìn)程對(duì)應(yīng)的路徑發(fā)生變化,這一塊稍微有一點(diǎn)繞:

只要讓我執(zhí)行 cd,按照之前的代碼就是進(jìn)程替換,和父進(jìn)程有什么關(guān)系,子進(jìn)程一跑就完了,曾經(jīng)的復(fù)出沒有任何意義了實(shí)際上是想讓父進(jìn)程的路徑發(fā)生變化。那么在我們現(xiàn)有的代碼中能做到讓父進(jìn)程的路徑發(fā)生變化嗎?不可能因?yàn)槲覀儸F(xiàn)有的代碼在進(jìn)行操作的時(shí)候最終的結(jié)果都會(huì)落實(shí)到 fork,然后 exec。這也就意味著,不管是什么命令,最后你都是創(chuàng)建子進(jìn)程,cd 命令也不除外。

所以,對(duì)我們來說我們此時(shí)就有一個(gè)需求了:如果有些行為是必須讓父進(jìn)程 shell 執(zhí)行的,不想讓子進(jìn)程執(zhí)行,這樣的場(chǎng)景下,絕對(duì)不能創(chuàng)建子進(jìn)程!進(jìn)位一旦創(chuàng)建了子進(jìn)程最后執(zhí)行任務(wù)的是子進(jìn)程,和你就沒有任何干系了,只能是父進(jìn)程自實(shí)現(xiàn)對(duì)應(yīng)的代碼。

這部分由 shell 自己執(zhí)行的命令,我們稱之為 內(nèi)建指令?(build-in) 。

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?下面我們就來解決路徑切換的問題:

/* Shell 內(nèi)置函數(shù): 路徑跳轉(zhuǎn) */
int ChangeDir(const char* new_path) {
    chdir(new_path);

    return 0;  // 調(diào)用成功
}

int main(void) 
{
    ...
        /* Step4. TODO 編寫后面的邏輯,內(nèi)建命令 */
        if (strcmp(command_args[0], "cd") == 0 && command_args[1] != NULL) {
            ChangeDir(command_args[1]);  // 讓調(diào)用方進(jìn)行路徑切換
            continue;
        }
    ...
}

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

??? 說明:在上層你看到的是個(gè)命令,但是在 shell 內(nèi)部本質(zhì)上是由父 shell 自己實(shí)現(xiàn)、調(diào)用的一個(gè)函數(shù)(并沒有創(chuàng)建子進(jìn)程),這種就是對(duì)應(yīng)上上層的 內(nèi)建命令。

內(nèi)建命令表現(xiàn)是用用戶層面的一條命令,本質(zhì)就是 Shell 內(nèi)部的一個(gè)函數(shù),由父 Shell 自己執(zhí)行,而不創(chuàng)建子進(jìn)程。

0x06 再次理解環(huán)境變量

我們上一章學(xué)過的 exec 的函數(shù),是可以直接執(zhí)行這指定的命令、環(huán)境變量的。

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維?獲取環(huán)境變量,直接遍歷環(huán)境變量列表就行:

// 方便測(cè)試,我們創(chuàng)建一個(gè) hello.c 文件

#include <stdio.h>

int main(void)
{
    /* 獲取環(huán)境變量列表 */
    extern char** environ;
    for (int i = 0; environ[i] != NULL; i++) {
        printf("[%d]: %s\n", i, environ[i]);
    }

    return 0;
}

環(huán)境變量具有全局屬性,我們可以在程序中添加環(huán)境變量的聲明:

extern char** environ;   // 環(huán)境變量指針聲明

            /* Step6: 程序替換 */
            execvp (
                command_args[0],  // 保存的是我們要執(zhí)行的程序名字
                command_args,
                environ   // 添加環(huán)境變量
            );

程序替換中,對(duì)于 exec 函數(shù)簇,如果如果函數(shù)名沒?e,所有的環(huán)境變量是會(huì)被繼承的。

不帶 e,環(huán)境變量依舊是可以被繼承的,如果我們自己定一個(gè)環(huán)境變量的指針數(shù)組,

它會(huì)覆蓋我們的環(huán)境變量列表,我現(xiàn)在不想覆蓋,我想新增:

/* 放置環(huán)境變量 */
void PutEnvMyShell(const char* new_env) {
    putenv(new_env);
}

        if (strcmp(command_args[0], "export") == 0 && command_args[1] != NULL) {
            PutEnvMyShell((char*)command_args[1]);   // export myval=100
            continue;
        } 

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

這是為什么呢?因?yàn)楫?dāng)前環(huán)境變量信息存儲(chǔ)在了 command_line 中,會(huì)被清空。

那么環(huán)境變量也會(huì)隨之清空而丟失,所以我么需要一個(gè)專門存儲(chǔ)環(huán)境變量的:

char env_buffer[NUM];  // 保存環(huán)境變量  just for test

        if (strcmp(command_args[0], "export") == 0 && command_args[1] != NULL) {
            // 目前,環(huán)境變量信息在 command_line,會(huì)被清空,環(huán)境變量也隨之清空
            // 此處我們需要自己保存一下環(huán)境變量的內(nèi)容
            strcpy(env_buffer, command_args[1]);
            PutEnvMyShell(env_buffer);   // export myval=100
            continue;
        }

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

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

?? 環(huán)境變量的數(shù)據(jù)在進(jìn)程的上下文中:

① 環(huán)境變量會(huì)被子進(jìn)程繼承下去,所以他會(huì)有全局屬性。
② 當(dāng)我們進(jìn)行程序替換時(shí), 當(dāng)前進(jìn)程的環(huán)境變量非但不會(huì)替換,而且是繼承父進(jìn)程的!

環(huán)境你不傳,默認(rèn)子進(jìn)程全部都會(huì)自動(dòng)繼承。

如果你 exel 函數(shù)簇帶 e,就相當(dāng)于你選擇了自己傳,就會(huì)覆蓋式地把原本的環(huán)境變量弄沒,然后你自己交給子進(jìn)程。如果不帶 e,那么環(huán)境變量就會(huì)自己被子進(jìn)程繼承。

如果既不想覆蓋系統(tǒng),也不想新增,所以我們采用 putEnv 的方式向父 Shell 導(dǎo)入新增一個(gè)它自己的環(huán)境變量,這樣的話原始的環(huán)境變量還在,我們能在 shell 上下文上給它新增環(huán)境變量。

所以,如何理解環(huán)境變量具有全局屬性?

因?yàn)樗械沫h(huán)境變量會(huì)被當(dāng)前進(jìn)程之下的所有子進(jìn)程默認(rèn)繼承下去。

如何在 Shell 內(nèi)部自己導(dǎo)入新增自己的環(huán)境變量?

putEnv,要注意的是,需要一個(gè)獨(dú)立的空間,放置環(huán)境變量的數(shù)據(jù)被改寫。

如何切換shell定位路徑,看表情包學(xué)Linux,linux,vim,運(yùn)維

?? [ 筆者 ]? ?王亦優(yōu)
?? [ 更新 ]? ?2023.3.21
? [ 勘誤 ]?? /* 暫無 */
?? [ 聲明 ]? ?由于作者水平有限,本文有錯(cuò)誤和不準(zhǔn)確之處在所難免,
              本人也很想知道這些錯(cuò)誤,懇望讀者批評(píng)指正!

?? 參考資料?

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

比特科技. Linux[EB/OL]. 2021[2021.8.31 xi文章來源地址http://www.zghlxwxcb.cn/news/detail-835416.html

到了這里,關(guān)于【看表情包學(xué)Linux】插敘:實(shí)現(xiàn)簡(jiǎn)易的 Shell | 通過內(nèi)建命令實(shí)現(xiàn)路徑切換 | 再次理解環(huán)境變量的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包