Linux bash命令行:bash命令行解釋器或者翻譯官,命令行輸入命令都是由bash解釋執(zhí)行的。
創(chuàng)新互聯(lián)是創(chuàng)新、創(chuàng)意、研發(fā)型一體的綜合型網(wǎng)站建設(shè)公司,自成立以來公司不斷探索創(chuàng)新,始終堅持為客戶提供滿意周到的服務(wù),在本地打下了良好的口碑,在過去的十多年時間我們累計服務(wù)了上千家以及全國政企客戶,如宴會酒店設(shè)計等企業(yè)單位,完善的項目管理流程,嚴(yán)格把控項目進(jìn)度與質(zhì)量監(jiān)控加上過硬的技術(shù)實力獲得客戶的一致稱贊。
一、命令行
二、查詢當(dāng)前登錄的用戶:
root
三、查詢當(dāng)前用戶主機(jī)名:
oldboy
四、查詢當(dāng)前用戶所在的路徑:
/root
五、切換用戶:
#切換到oldboy用戶
(#$是普通用戶的提示符。一般大臣,布衣。)?
oldboy
六、符號的意思
~? ? ? ? 用戶家目錄
-? ? ? ? ? 上一次所在的目錄
.? ? ? ? ?表示當(dāng)前目錄
..? ? ? ? ?上一級目錄
../.. ? ? ?表示上一級的上一級目錄
我們平時所說的 Shell 可以理解為 Linux 系統(tǒng)提供給用戶的使用界面。Shell 為用戶提供了輸入命令和參數(shù)并可得到命令執(zhí)行結(jié)果的環(huán)境。當(dāng)一個用戶登錄 Linux 之后,系統(tǒng)初始化程序 init 就根據(jù) /etc/passwd 文件中的設(shè)定,為每個用戶運(yùn)行一個被稱為 Shell(外殼)的程序。
確切地說,Shell 是一個命令行解釋器,它為用戶提供了一個向 Linux 內(nèi)核發(fā)送請求以便運(yùn)行程序的界面系統(tǒng)級程序,用戶可以用 Shell 來啟動、掛起、停止甚至編寫一些程序。
Shell 處在內(nèi)核與外層應(yīng)用程序之間,起著協(xié)調(diào)用戶與系統(tǒng)的一致性、在用戶與系統(tǒng)之間進(jìn)行交互的作用。圖 1 是 Linux 系統(tǒng)層次結(jié)構(gòu)圖,Shell 接收用戶輸入的命令,并把用戶的命令從類似 abed 的 ASCII 碼解釋為類似 0101 的機(jī)器語言,然后把命令提交到系統(tǒng)內(nèi)核處理;當(dāng)內(nèi)核處理完畢之后,把處理結(jié)果再通過 Shell 返回給用戶。
換句話說:
Shell 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程序設(shè)計語言。
Shell 是指一種應(yīng)用程序,這個應(yīng)用程序提供了一個界面,用戶通過這個界面訪問操作系統(tǒng)內(nèi)核的服務(wù)。
Ken Thompson 的 sh 是第一種 Unix Shell,Windows Explorer 是一個典型的圖形界面 Shell。
Shell 與其他 Linux 命令一樣,都是實用程序,但它們之間還是有區(qū)別的。一旦用戶注冊到系統(tǒng)后,Shell 就被系統(tǒng)裝入內(nèi)存并一直運(yùn)行到用戶退出系統(tǒng)為止;而一般命令僅當(dāng)被調(diào)用時,才由系統(tǒng)裝入內(nèi)存執(zhí)行。
與一般命令相比,Shell 除了是一個命令行解釋器,同時還是一門功能強(qiáng)大的編程語言,易編寫,易調(diào)試,靈活性較強(qiáng)。作為一種命令級語言,Shell 是解釋性的,組合功能很強(qiáng),與操作系統(tǒng)有密切的關(guān)系,可以在 Shell 腳本中直接使用系統(tǒng)命令。大多數(shù) Linux 系統(tǒng)的啟動相關(guān)文件(一般在 /etc/rc.d 目錄下)都是使用 Shell 腳本編寫的。
同傳統(tǒng)的編程語言一樣,Shell 提供了很多特性,這些特性可以使 Shell 腳本編程更為有用,如數(shù)據(jù)變量、參數(shù)傳遞、判斷、流程控制、數(shù)據(jù)輸入和輸出、子程序及中斷處理等。
說了這么多,其實我們在 Linux 中操作的命令行界面就是 Linux 的 Shell,也就是 Bash,但是我們的圖形界面是 Shell 嗎?其實從廣義講,圖形界面當(dāng)然也是 Shell,因為它同樣用來接收用戶的操作,并傳遞到內(nèi)核進(jìn)行處理。不過,這里的 Shell 主要指的是 Bash。
Shell 腳本
Shell 腳本(shell script),是一種為 shell 編寫的腳本程序。
業(yè)界所說的 shell 通常都是指 shell 腳本,但讀者朋友要知道,shell 和 shell script 是兩個不同的概念。
由于習(xí)慣的原因,簡潔起見,本文出現(xiàn)的 "shell編程" 都是指 shell 腳本編程,不是指開發(fā) shell 自身。
Shell的分類
目前 Shell 的版本有很多種,如 Bourne Shell、C Shell、Bash、ksh、tcsh 等,它們各有特點,下面簡要介紹一下。
最重要的 Shell 是 Bourne Shell,這個命名是為了紀(jì)念此 Shell 的發(fā)明者 Steven Bourne。從 1979 年起,UNIX 就開始使用 Boume Shell。Bourne Shell 的主文件名為 sh,開發(fā)人員便以 sh 作為 Bourne Shell 的主要識別名稱。
雖然 Linux 與 UNIX 一樣,可以支持多種 Shell,但 Boume Shell 的重要地位至今仍然沒有改變,許多 UNIX 系統(tǒng)中仍然使用 sh 作為重要的管理工具。它的工作從開機(jī)到關(guān)機(jī),幾乎無所不包。在 Linux 中,用戶 Shell 主要是 Bash,但在啟動腳本、編輯等很多工作中仍然使用 Bourne Shell。
C Shell 是廣為流行的 Shell 變種。C Shell 主要在 BSD 版的 UNIX 系統(tǒng)中使用,發(fā)明者是柏克萊大學(xué)的 Bill Joy。C Shell 因為其語法和 C 語言類似而得名,這也使得 UNIX 的系統(tǒng)工程師在學(xué)習(xí) C Shell 時感到相當(dāng)方便。
Bourne Shell 和 C Shell 形成了 Shell 的兩大主流派別,后來的變種大都吸取這兩種 Shell 的特點,如 Korn、 tcsh 及 Bash。
Bash Shell 是 GNU 計劃的重要工具之一,也是 GNU 系統(tǒng)中標(biāo)準(zhǔn)的 Shell。Bash 與 sh 兼容,所以許多早期開發(fā)出來的 Bourne Shell 程序都可以繼續(xù)在 Bash 中運(yùn)行。現(xiàn)在使用的 Linux 就使用 Bash 作為用戶的基本 Shell。
Bash 于 1988 年發(fā)布,并在 1995-1996年推出Bash 2.0。在這之前,廣為使用的版本是1.14,Bash 2.0增加了許多新的功能,以及具備更好的兼容性。表 2 中詳細(xì)列出了各版本的具體情況。
注意,Shell 的兩種主要語法類型有 Bourne 和 C,這兩種語法彼此不兼容。Boume 家族主要包括 sh、ksh、Bash、psh、zsh;C 家族主要包括 csh、tcsh(Bash 和 zsh 在不同程序上支持 csh 的語法)。
本章講述的腳本編程就是在 Bash 環(huán)境中進(jìn)行的。不過,在 Linux 中除了可以支持 Bash,還可以支持很多其他的 Shell。我們可以通過 /etc/shells 文件來査詢 Linux 支持的 Shell。命令如下:
在 Linux 中,這些 Shell 是可以任意切換的,命令如下:
用戶信息文件 /etc/passwd 的最后一列就是這個用戶的登錄 Shell。命令如下:
大家可以看到,root 用戶和其他可以登錄系統(tǒng)的普通用戶的登錄 Shell 都是 /bin/bash,也就是 Linux 的標(biāo)準(zhǔn) Shell,所以這些用戶登錄之后可以執(zhí)行權(quán)限允許范圍內(nèi)的所有命令。不過,所有的系統(tǒng)用戶(偽用戶)因為登錄 Shell 是 /sbin/ndogin,所以不能登錄系統(tǒng)。
筆記:
sh/bash/csh/Tcsh/ksh/pdksh等shell的區(qū)別
姓名:羅學(xué)元? ? ? ?學(xué)號:21181214375 ????學(xué)院:廣州研究院
【嵌牛導(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ù)改變當(dāng)前路徑。
對于外部命令,需要創(chuàng)建一個子進(jìn)程來執(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 -這條命令
//================================================================================
//每次敲回車輸出當(dāng)前所在用戶信息
//普通用戶和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; //主機(jī)名
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記錄當(dāng)前工作目錄的絕對路徑
char oldpwd[STRLEN]={0};
getcwd(oldpwd,STRLEN-1);
if(-1==chdir(path))//反之則不是空,則通過chdir系統(tǒng)調(diào)用進(jìn)入到該目錄中
{
? ? 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為空,則進(jìn)入下一輪循環(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);
}
//進(jìn)行命令拼接,路徑+名稱
strcat(path,myargv[0]);
//替換進(jìn)程 例如:/bin/ls
execv(path,myargv);
perror("\033[;31mexecv error\033[0m");
}
//處理僵死進(jìn)程
else
{
wait(NULL);
}
}
}
運(yùn)行結(jié)果如下 :
異常處理如下:
若是第一次運(yùn)行程序,則不能使用cd - 命令,因為此時還沒有歷史路徑
若進(jìn)入一個不存在的目錄則會報錯,沒有這個文件或目錄
若直接輸入一個不存在的無法識別的命令,也會報錯。