Shell是應(yīng)用于Linux系統(tǒng)中的命令解釋器,其作用和Windows系統(tǒng)的命令提示符一樣。都是為當前用戶提供與系統(tǒng)內(nèi)核進行交互操作的一種用戶界面。
創(chuàng)新互聯(lián)建站是一家企業(yè)級云計算解決方案提供商,超15年IDC數(shù)據(jù)中心運營經(jīng)驗。主營GPU顯卡服務(wù)器,站群服務(wù)器,成都托管服務(wù)器,海外高防服務(wù)器,服務(wù)器機柜,動態(tài)撥號VPS,海外云手機,海外云服務(wù)器,海外服務(wù)器租用托管等。
姓名:羅學元? ? ? ?學號:21181214375 ????學院:廣州研究院
【嵌牛導(dǎo)讀】shell命令解釋器該包含哪些部分
【嵌牛鼻子】shell命令解釋器該包含哪些部分
【嵌牛提問】shell命令解釋器該包含哪些部分
我們所做的這個簡單的shell命令解釋器可以實現(xiàn)簡單的常用的基本命令,如ls、pwd、cd、cd - 、cd ~ 等
根據(jù)簡單命令的定義,它的第一個參數(shù)是要執(zhí)行的命令,后面的參數(shù)作為該命令的參數(shù)。
要執(zhí)行的命令有兩種情況:
一種是外部命令: 也就是對應(yīng)著磁盤上的某個程序,例如 pwd、ls等等。對于這種外部命令,我們首先要到指定的路徑下找到它,然后再執(zhí)行它。
另一種是內(nèi)部命令:內(nèi)部命令并不對應(yīng)磁盤上的程序,例如cd等等,它需要shell自己來決定該如何執(zhí)行。例如對 cd 命令,shell就應(yīng)該根據(jù)它后面的參數(shù)改變當前路徑。
對于外部命令,需要創(chuàng)建一個子進程來執(zhí)行它,本質(zhì)就是fork+exec
#include stdio.h
#include stdlib.h
#include assert.h
#include string.h
#include pwd.h
#include sys/utsname.h
#include sys/types.h
#include unistd.h
#define MAX 10
#define STRLEN 128
#define PATH "/bin/" //系統(tǒng)bin路徑位置
char OLDPWD[STRLEN]={0}; //記錄上一次的命令,為了cd -這條命令
//================================================================================
//每次敲回車輸出當前所在用戶信息
//普通用戶和root用戶的提示符區(qū)別
void Printf_Info()
{
char flag='$';
struct passwd *pw=getpwuid(getuid());
assert(pw!=NULL);
//uid為0則為root用戶
if(pw-pw_uid==0)
{
flag='#';
}
struct utsname hostname; //主機名
uname(hostname);
char node[STRLEN]={0};
strcpy(node,hostname.nodename); //獲取網(wǎng)絡(luò)上的名稱
char* name=strtok(node,".");
//獲取絕對路徑
char path[STRLEN]={0};
getcwd(path,STRLEN-1);
char*p=path+strlen(path); //p指向絕對路徑的末尾
while(*p!='/')
{
p--;
}
//p指向路徑末尾往前的第一個‘/’位置處
if(strlen(path)!=1)
{
p++; //++前,p-'/'
}
if(strcmp(path,pw-pw_dir)==0)
{
p="~";
}
printf("\033[;32mMyBash[%s@%s %s]%c\033[0m",pw-pw_name,name,p,flag);
//? \033[47;31mThis is a color test\033[0m? 設(shè)置打印結(jié)果的顏色
fflush(stdout);
}
//================================================================================
void Mycd(char*path)
{
//第一個字符串為cd而第二為空 如:cd 則結(jié)束本輪循環(huán)
if(path==NULL)
{
exit(0);
}
//cd ~ 回到用戶根目錄
if(strcmp(path,"~")==0)
{
? ? struct passwd*pw=getpwuid(getuid());
? ? path=pw-pw_dir;
}
//cd - 回到上一次的位置
if(strcmp(path,"-")==0)?
{
? //若是第一次輸入命令,則cd -命令不存在!
? ? if(strlen(OLDPWD)==0)
? ? {
? ? ? ? printf("\033[;31mMyBash:cd:OLDPWD not set\n\033[0m");
? ? ? ? return ;
? ? }
? ? //否則把上一次的命令給path
? ? path=OLDPWD;
}
//getpwd記錄當前工作目錄的絕對路徑
char oldpwd[STRLEN]={0};
getcwd(oldpwd,STRLEN-1);
if(-1==chdir(path))//反之則不是空,則通過chdir系統(tǒng)調(diào)用進入到該目錄中
{
? ? char err[128]="\033[;31mMybash: cd \033[0m";
? ? strcat(err,path);
? ? perror(err);
}
//每次執(zhí)行完cd命令后,把工作路徑賦給OLDPWD
strcpy(OLDPWD,oldpwd);
}
//================================================================================
//命令分割函數(shù)
void Strtok_cmd(char*buff,char*myargv[])
{
char *s=strtok(buff," "); //分割輸入的字符串
if(s==NULL) //如果s為空,則進入下一輪循環(huán)
{
exit(0);
}
myargv[0]=s; //把分割出來的第一個字符串放在myargv[0]中
int i=1;
while((s=strtok(NULL,""))!=NULL) //把后續(xù)分割出來的字符串依次存放在數(shù)組中
{
myargv[i++]=s;
}
}
//===============================================================
int main()
{
while(1)
{
char buff[128]={0};
Printf_Info();
//從終端獲取命令存入buff中
fgets(buff,128,stdin);
buff[strlen(buff)-1]=0;
char *myargv[MAX]={0};
//分割輸入的命令
Strtok_cmd(buff,myargv);
//如果輸入exit則退出循環(huán)
if(strcmp(myargv[0],"exit")==0)
{
exit(0);
}
//如果分割出來的第一個字符串為cd
else if(strcmp(myargv[0],"cd")==0)
{
Mycd(myargv[1]);
continue;
}
//若是系統(tǒng)調(diào)用,直接替換fork+exec
pid_t pid=fork();
assert(pid!=-1);
if(pid==0)
{
char path[256]={0};
if(strncmp(myargv[0],"./",2)!=0 strncmp(myargv[0],"/",1)!=0)
{
//先把路徑放入path中
strcpy(path,PATH);
}
//進行命令拼接,路徑+名稱
strcat(path,myargv[0]);
//替換進程 例如:/bin/ls
execv(path,myargv);
perror("\033[;31mexecv error\033[0m");
}
//處理僵死進程
else
{
wait(NULL);
}
}
}
運行結(jié)果如下 :
異常處理如下:
若是第一次運行程序,則不能使用cd - 命令,因為此時還沒有歷史路徑
若進入一個不存在的目錄則會報錯,沒有這個文件或目錄
若直接輸入一個不存在的無法識別的命令,也會報錯。
就是執(zhí)行命令用的,不同的操作系統(tǒng)有不同的解釋器。
Window下也叫“命令提示符”,可以在開始運行那里輸入CMD就會跳出來。
linux的命令解釋器叫shell,但linux又有多種不同的shell,常見的有Bourne shell(簡稱sh),C shell(簡稱csh),Korn shell(簡稱ksh)和Bourne Again shell(簡稱bash)。
ubuntu默認的shell是bash。
而且還有幾種不同的終端,但命令和腳本還是由shell來解釋和執(zhí)行的。終端與shell沒有對應(yīng)關(guān)系
Linux bash命令行:bash命令行解釋器或者翻譯官,命令行輸入命令都是由bash解釋執(zhí)行的。
一、命令行
二、查詢當前登錄的用戶:
root
三、查詢當前用戶主機名:
oldboy
四、查詢當前用戶所在的路徑:
/root
五、切換用戶:
#切換到oldboy用戶
(#$是普通用戶的提示符。一般大臣,布衣。)?
oldboy
六、符號的意思
~? ? ? ? 用戶家目錄
-? ? ? ? ? 上一次所在的目錄
.? ? ? ? ?表示當前目錄
..? ? ? ? ?上一級目錄
../.. ? ? ?表示上一級的上一級目錄