我写了个esxi shell cd命令,如何实现cd命令的功能

怎么学 linux shell? - 知乎有问题,上知乎。知乎作为中文互联网最大的知识分享平台,以「知识连接一切」为愿景,致力于构建一个人人都可以便捷接入的知识分享网络,让人们便捷地与世界分享知识、经验和见解,发现更大的世界。427被浏览<strong class="NumberBoard-itemValue" title="4分享邀请回答#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "args count must & 1"
echo "Uage: bash +x example01.sh [args...]"
if [[ $arg -gt 10 ]]; then
echo "$arg & 10"
echo "$arg & 10"
这个脚本的调用方式如下:bash +x example01.sh 5
2).数组、函数传参数,循环下面的例子展示了数组、函数、循环等基本使用。#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "args count must & 1"
echo "Uage: bash +x example01.sh [args...]"
for arg in $ do
function fun() {
fun "hello shell"
echo "Linux"
注意,函数fun中的$1,获取的是函数参数,不是脚本调用时传入的参数。$@ 是获取脚本调用时传入的参数列表。3).while 循环以及其他几种循环、case、表达式expr的使用#!/bin/bash
if [[ $# -lt 1 ]]; then
echo "args count must & 1"
echo "Uage: bash +x example01.sh [args...]"
case $1 in
"install" )
echo "operation type is install"
"uninstall" )
echo "operation type is uninstall"
echo "operation type is not support"
for ((i=0;i&3;i++))
if ((i==1))
for i in `seq 5`
echo "loop $i"
注意这里的case * 并不是所有,而是输入值不在case中,相当于default. 在循环中可以使用continue/break等关键字,非常类似java等其他语言的循环。4).脚本之间互相引用通过source 或者 . 的方式可以引用另一个脚本中的函数或者变量first.shfunction fun(){
echo "i am from first."
file=first
second.sh. first.sh
echo $file
使用bash +x second.sh执行,在second.sh 中可以调用fun函数和使用file变量。这里的.和source都可以实现引用first文件中的变量。注意: 如果同时引用了多个脚本的同一个变量名的变量,后面的值会覆盖前面的变量而不会报错。5).关于错误处理a)在shell中有一个变量 $? ,这个变量记录的是上次脚本执行的结果,如果正常结束则是0,否则是非0值;b)如果在shell脚本中通过set -o errexit来实现遇到错误就退出,这样能够避免产生更多的错误;c)在shell执行过程中如果出错,可以通过重定向的方式,输出到文件中,比如Command && filename2&&16).字典shell中的字典是非常好的数据结构,能够很方便地处理配置#!/bin/bash
set -o errexit
eval "hkey_$1"="$2"
eval echo '${'"hkey_$1"'}'
hput k1 v1
declare -A dic
dic=([key1]="value1" [key2]="value2" [key3]="value3")
echo ${dic["key1"]}
# output all key
echo ${!dic[*]}
#outpull all value
echo ${dic[*]}
# access all
for key in $(echo ${!dic[*]})
echo "$key : ${dic[$key]}"
执行之后,输出如下:v1
key3 key2 key1
value3 value2 value1
key3 : value3
key2 : value2
key1 : value1
7).文本处理sed 命令能够对对文本进行操作。比如有一个文件sedfile,内容如下:1
执行 "sed '1,3d' sedfile,则会输出4,5 两行,即对1,2,3行做了删除处理,注意这时文件里面并没有删掉这两行。除了删除之外,还可以做替换操作。root@ubuntu:~/codelab# sed 's/1/0/g' sedfile
root@ubuntu:~/codelab# cat sedfile
我们发现,在输出时,将1替换成了0;文本处理还有一个非常强大的工具-awk我们首先看看awk的基本处理-按照逗号(,)分割获取想要的文本;root@ubuntu:~/codelab# cat awkfile
this,is,a,awk,file
this,is,a,awk,file
root@ubuntu:~/codelab# cat awkfile | awk -F ',' '{print $0}'
this,is,a,awk,file
this,is,a,awk,file
root@ubuntu:~/codelab# cat awkfile | awk -F ',' '{print $1}'
root@ubuntu:~/codelab#
这里我们可以看到awk可以按照任意形式分割文本,然后输出;8).特殊变量和值下列变量通常具有固定意义$#
表示变量的个数,常用于循环
当前命令行所有参数。置于双引号中,表示个别参数
当前命令行所有参数。置于双引号中,表示将命令行所有参数当初一个单独参数
$-(连字号)
在引用数给予Shell的选项
表示上一个命令退出的状态
表示当前进程编号
表示当前程序名称
表示最近一个后台命令的进程编号
表示当前用户根目录
表示内部的字段分隔符
当前locale默认名称
父进程编号
当前工作目录
下列特殊值可以帮助排查问题0
命令退出失败,失败返回的相关值由程序定义(譬如,程序内退出只执行 exit 2,则返回为2)
命令找到了,但无法执行
命令找不到
命令因受到信号而死亡
9.定时任务windows系统下有定时任务,在linux系统上也一样有定时任务。使用系统自带的crontab即可实现;我的系统上执行 cat /etc/crontab的输出如下:root@ubuntu:~/codelab# cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user
cd / && run-parts --report /etc/cron.hourly
test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
从这里我们可以看出cron是如何使用的,这里设定了cron使用shell,下面是命令的设置方式。minute: 表示分钟,可以是从0到59之间的任何整数。
hour:表示小时,可以是从0到23之间的任何整数。
day:表示日期,可以是从1到31之间的任何整数。
month:表示月份,可以是从1到12之间的任何整数。
week:表示星期几,可以是从0到7之间的任何整数,这里的0或7代表星期日。
command:要执行的命令,可以是系统命令,也可以是自己编写的脚本文件。
我们可以使用如下一些基础命令;usage:
crontab [-u user] file
crontab [ -u user ] [ -i ] { -e | -l | -r }
(default operation is replace, per 1003.2)
(edit user's crontab)
(list user's crontab)
(delete user's crontab)
(prompt before deleting user's crontab)
10).技巧a)判断参数是否是数字。#!/bin/sh
#1. $1是脚本的第一个参数,这里作为awk命令的第一个参数传入给awk命令。
#2. 由于没有输入文件作为输入流,因此这里只是在BEGIN块中完成。
#3. 在awk中ARGV数组表示awk命令的参数数组,ARGV[0]表示命令本身,ARGV[1]表示第一个参数。
#4. match是awk的内置函数,返回值为匹配的正则表达式在字符串中(ARGV[1])的起始位置,没有找到返回0。
#5. 正则表达式的写法已经保证了匹配的字符串一定是十进制的正整数,如需要浮点数或负数,仅需修改正则即可。
#6. awk执行完成后将结果返回给isdigit变量,并作为其初始化值。
#7. isdigit=`echo $1 | awk '{ if (match($1, "^[0-9]+$") != 0) print "true"; else print "false" }' `
#8. 上面的写法也能实现该功能,但是由于有多个进程参与,因此效率低于下面的写法。
isdigit=`awk 'BEGIN { if (match(ARGV[1],"^[0-9]+$") != 0) print "true"; else print "false" }' $1`
if [[ $isdigit == "true" ]]; then
echo "This is numeric variable."
number=$1&pre code_snippet_id="1930260" snippet_file_name="blog__9421840" name="code" class="plain"&fi&/pre&
b) 根据系统给变量赋值,确保可移植性#1. 通过uname命令获取当前的系统名称,之后再根据OS名称的不同,给PING变量赋值不同的ping命令的全称。
osname=`uname -s`
#2. 可以在case的条件中添加更多的操作系统名称。
case $osname in
PING=/usr/sbin/;
"FreeBSD")
PING=/sbin/;
PING=/usr/sbin/;
总结这些只是shell中的最基础部分,shell 其实是一种非常高效、强大的语言,不断学习和积累一定会越来越熟练。你想更深入了解学习Linux知识体系,你可以看一下我们花费了一个多月整理了上百小时的几百个知识点体系内容: 937 条评论分享收藏感谢收起597 条评论分享收藏感谢收起Linux shell 命令cd是怎么实现的?放在哪个文件夹?_百度知道
Linux shell 命令cd是怎么实现的?放在哪个文件夹?
我有更好的答案
cd命令通常没有对应的可执行文件,是shell的内置命令,bash的源码中有cd的实现(bash可以从gnu官网下载),代码不多。大致做了这些事:1、更新当前shell的环境变量$PWD的值2、调用系统调用chdirchdir的实现在内核中。
采纳率:68%
cd是shell内置命令,可以在shell的源码中找到实现,比如bash就可以看cd.def
请问,在哪里能看到cd.def?
看来你要上网搜一下linux的命令其应用,然后尝试在虚拟机用
呵呵……谢谢你的回答,我的意思是cd命令式怎么写出来的,而不是cd怎么使用。
为您推荐:
其他类似问题
您可能关注的内容
shell的相关知识
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。编写自己的Shell解释器
我的图书馆
编写自己的Shell解释器
shellshell linux
&&&&&& linuxc
shellshell
Shell解释器是什么?
Shelllinuxshell /bin/bash/bin/shshell
提示:在 /etc/passwd 文件中,每个用户对应的最后一项,就指定了该用户登陆之后,要执行的shell解释器程序。
bash 是一个兼容于 sh 的命令语言解释器,它从标准输入或者文件中读取命令并执行。它的意图是实现 IEEE POSIX标准中对 shell和工具所规范的内容。
Shell解释器的作用
&&&&&& [root@stevens root]#
bash bash bashbash
[root@stevens root]#& echo “hello, world”
bashhello world
[root@stevens root]#& cd /tmp
shell linux
exitlogout bash
Shell语法梗概
[root@stevesn root]# aaaaaa
bash: aaaaaa: command not found
Shell IEEE POSIXshelltools
shell shell
man bash bash
bashshell shell
a=10 b=20 export a b
就是两个词,一个 ls,一个 /tmp
3、可以出现重定向符号,重定向符号是“&”和“&”,例如:
echo “hello world” & /tmp/log
||& &&& &&&&&& ; & ;;& ( )&& |& &newline&
echo “100” ; echo “200”
echo “hello world” echo
echo “hello world”1 echo 2
echo “hello world” | wc –l
echo “hello world”
“hello world”
wc –l wc –l
echo “hello world” | wc – echo “nice to meet you”
实现shell实例
logout exit
while(1) {
&&&&&& print_prompt();
&&&&&& get_input();
&&&&&& parse_input();
&&&&&& if(“logout” || “exit”)
&&&&&&&&&&&&&
&&&&&& do_cmd();
int len = 0;
char buf[300];
ch = getchar();
while(len & BUFSIZ && ch != '/n') {
&&&&&& buf[len++] =
&&&&&& ch = getchar();
if(len == BUFSIZ) {
&&&&&& printf("command is too long/n");
buf[len] = '/n';
buf[len] = 0;
bash &--& tab shell
bash GNU readline
man readline
char prompt[200];
while(1) {
&&&&&& set_prompt(prompt);
&&&&&& if(!(line = readline(prompt)))
&&&&&&&&&&&&&
set_prompt()
readline() line
lex yacc Lex
yacc GNUopen source
shell bash
tab键或者空格)
;”、“&”、“&”或“|”
”);&&|POSIX”’`
’/n’ shell
"/""&&&&&&&&&&& {BEGIN QUOTE;}
&QUOTE&[^/n"]+& {add_arg(yytext);}
&QUOTE&"/""&&&& {BEGIN 0;}
&QUOTE&/n&&&&&& {BEGIN 0; do_list_cmd(); reset_args();}
";"&&&&&&&&&&&& {add_simple_arg(yytext);}
"&"&&&&&&&&&&&& {add_simple_arg(yytext);}
"&"&&&&&&&&&&&& {add_simple_arg(yytext);}
"|"&&&&&&&&&&&& {add_simple_arg(yytext);}
[^ /t/n|&&;"]+& {add_arg(yytext);}
/n&&&&&&&&&&&&& {do_list_cmd(); reset_args();}
.&&&&&&&&&&&&&& ;
1"/""&&&&&&&&&&& {BEGIN QUOTE;}
2&QUOTE&[^/n"]+& {add_arg(yytext);}
3&QUOTE&"/""&&&& {BEGIN 0;}
4&QUOTE&/n&&&&&& {BEGIN 0; do_list_cmd(); reset_args();}
1、 “ QUOTE ;&&|
2、 QUOTE add_arg()
4、QUOTE do_list_cmd()
5";"&&&&&&&&&&&&& {add_simple_arg(yytext);}
6"&"&&&&&&&&&&&&& {add_simple_arg(yytext);}
7"&"&&&&&&&&&&&&& {add_simple_arg(yytext);}
8"|"&&&&&&&& &&&&&&{add_simple_arg(yytext);}
9[^ /t/n|&&;"]+&&&&& {add_arg(yytext);}
10/n&&&&&&&&&&&&&& {do_list_cmd(); reset_args();}
5、; add_simple_arg()
6、 & add_simple_arg()
7、 & add_simple_arg()
8、| add_simple_arg()
9、tab’/n’| &&;
10、 do_list_cmd()
do_list_cmd()
; do_pipe_cmd()
static void do_list_cmd()
&&&&&& int i = 0;
&&&&&& int j = 0;
&&&&&& char*
&&&&&& while(argbuf[i]) {
&&&&&&&&&&&&& if(strcmp(argbuf[i], ";") == 0) {//& ;
&&&&&&&&&&&&&&&&&&&& p = argbuf[i];
&&&&&&&&&&&&&&&&&&&& argbuf[i] = 0;
&&&&&&&&&&&&&&&&&&&& do_pipe_cmd(i-j, argbuf+j);
&&&&&&&&&&&&&&&&&&&& argbuf[i] =
&&&&&&&&&&&&&&&&&&&& j = ++i;
&&&&&&&&&&&&& } else
&&&&&&&&&&&&&&&&&&&& i++;
&&&&&& do_pipe_cmd(i-j, argbuf+j);
IPCunix14unix24FIFO
[root@stevens root]#& echo “hello world”|wc –c |wc –l
echo “hello world” hello world
wc –c hello worldwc –c 12
wc –l1211
do_pipe_cmd()
postfd prepipe
|do_simple_cmd() do_simple_cmd()
prepipedo_simple_cmd()
int i = 0, j = 0, prepipe = 0;
int prefd[2], postfd[2];
while(argv[i]) {
&&&&&& if(strcmp(argv[i], "|") == 0) { // pipe
&&&&&&&&&&&&& p = argv[i];
&&&&&&&&&&&&& argv[i] = 0;
&&&&&&&&&&&&& pipe(postfd); &&&&&&& //create the post pipe
&&&&&& &&&&&& if(prepipe)&&&&&
&&&&&&&&&&&&&&&&&&&& do_simple_cmd(i-j, argv+j, prefd, postfd);
&&&&&&&&&&&&& else
&&&&&&&&&&&&&&&&&&&& do_simple_cmd(i-j, argv+j, 0, postfd);
&&&&&&&&&&&&& argv[i] =
&&&&&&&&&&&&& prepipe = 1;
&&&&&&&&&&&&& prefd[0] = postfd[0];
&&&&&&&&&&&&& prefd[1] = postfd[1];
&&&&&&&&&&&&& j = ++i;
&&&&&& } else
&&&&&&&&&&&&& i++;
if(prepipe)
&&&&&& do_simple_cmd(i-j, argv+j, prefd, 0);
&&&&&& do_simple_cmd(i-j, argv+j, 0, 0);
cdechoshell cd shell
execv() execunix8
do_exit()do_cd()do_echo()do_export()do_history()
echo “hello world” & xxx
echo “hello world”
predo_for_redirect()
makefile shell
喜欢该文的人也喜欢如何在shell脚本中执行cd命令_百度知道
如何在shell脚本中执行cd命令
我有更好的答案
可以使用eval命令。eval命令,如同熟悉的其他脚本语言,会将它的参数做为命令执行。eval命令将会首先扫描命令行进行所有的替换,然后再执行命令。该命令使用于那些一次扫描无法实现其功能的变量。该命令对变量进行两次扫描。这些需要进行两次扫描的变量有时候被称为复杂变量。命令格式:eval [参数]补充说明:eval可读取一连串的参数,然后再依参数本身的特性来执行。参数不限数目,彼此之间用分号分开。用法示例:将字符串变量s的值作为命令执行s=&ls&eval $s
采纳率:92%
来自团队:
为您推荐:
其他类似问题
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。&nbsp>&nbsp
&nbsp>&nbsp
&nbsp>&nbsp
Linux下具有基本功能的shell的具体代码实现(详细)
摘要:在前几个月对Linux的学习过程中,一直在与shell进行交互,感觉shell充满了神秘感。偶然看到一篇文章讲解了shell的实现,感觉也不是很难的样子,于是自己也开始开发自己的minishell,顺便也巩固了前一段时间学习的linux系统编程的知识。先来展示一下我的这个minishell实现的功能:1.支持ls,touch,wc等外部命令2.支持输入输出重定向符3.支持管道命令4.支持后台作业5.支持cd,jobs,kill,exit等内部命令(自己还写了一个about命令
在前几个月对Linux的学习过程中,一直在与shell进行交互,感觉shell充满了神秘感。偶然看到一篇文章讲解了shell的实现,感觉也不是很难的样子,于是自己也开始开发自己的minishell,顺便也巩固了前一段时间学习的linux系统编程的知识。
先来展示一下我的这个minishell实现的功能:
1. 支持ls,touch,wc 等外部命令2. 支持输入输出重定向符
3. 支持管道命令
4 .支持后台作业
5. 支持cd,jobs,kill,exit等内部命令(自己还写了一个about 命令 ^ _ ^)
6. 支持对ctrl+c 和ctrl +z 信号的处理
接下来我们按照编写的步骤一一来分析:
(一)命令的解析
输入命令的解析在本程序中占到了很大的比重,虽然像这种解析普通命令的程序(正则表达式太难了。。)的解释器难度不大,但是健壮性和全面性还是需要周全考虑的。这里采用了分段解析,先除去起始空格,制表符等,并以此和一些‘|’,‘&’为分割界限来解析命令至COMMAND结构体。直接看代码吧,注释很详细!
/* * 解析命令 * 成功返回解析到的命令个数,失败返回-1 */int parse_command(void){ /* cat & test.txt | grep -n public & test2.txt &; */ if (check(&/n&)) return 0; /* 判断是否内部命令并执行它 */ if (builtin()) return 0; /* 1、解析第一条简单命令 */ get_command(0); /* 2、判定是否有输入重定向符 */ if (check(&&&)) getname(infile); /* 3、判定是否有管道 */ for (i=1; i&PIPELINE; ++i) { if (check(&|&)) get_command(i); } /* 4、判定是否有输出重定向符 */ if (check(&&&)) { if (check(&&&)) append = 1; getname(outfile); } /* 5、判定是否后台作业 */ if (check(&&;&)) backgnd = 1; /* 6、判定命令结束‘/n’*/ if (check(&/n&)) { cmd_count = return cmd_ } else { fprintf(stderr, &Command line syntax error/n&); return -1; }}/* * 解析简单命令至cmd[i] * 提取cmdline中的命令参数到avline数组中, * 并且将COMMAND结构中的args[]中的每个指针指向这些字符串 */void get_command(int i){ /* cat & test.txt | grep -n public & test2.txt &; */ int j = 0; while (*lineptr != '/0') { /* 去除空格 */ while (*lineptr == ' ' || *lineptr == '/t') lineptr++; /* 将第i条命令第j个参数指向avptr */ cmd[i].args[j] = /* 提取参数 */ while (*lineptr != '/0' &;&; *lineptr != ' ' &;&; *lineptr != '/t' &;&; *lineptr != '&' &;&; *lineptr != '&' &;&; *lineptr != '|' &;&; *lineptr != '&;' &;&; *lineptr != '/n') { /* 参数提取至avptr指针所向的数组avline */ *avptr++ = *lineptr++; inword = 1; } *avptr++ = '/0'; switch (*lineptr) { case ' ': case '/t': inword = 0; j++; case '&': case '&': case '|': case '&;': case '/n': if (inword == 0) cmd[i].args[j] = NULL; default: /* for '/0' */ } }}/* * 将lineptr中的字符串与str进行匹配 * 成功返回1,lineptr移过所匹配的字符串 * 失败返回0,lineptr保持不变 */int check(const char *str){ char *p; while (*lineptr == ' ' || *lineptr == '/t') lineptr++; p = while (*str != '/0' &;&; *str == *p) { str++; p++; } if (*str == '/0') { lineptr = /* lineptr移过所匹配的字符串 */ return 1; } /* lineptr保持不变 */ return 0;}void getname(char *name){ while (*lineptr == ' ' || *lineptr == '/t') lineptr++; while (*lineptr != '/0' &;&; *lineptr != ' ' &;&; *lineptr != '/t' &;&; *lineptr != '&' &;&; *lineptr != '&' &;&; *lineptr != '|' &;&; *lineptr != '&;' &;&; *lineptr != '/n') { *name++ = *lineptr++; } *name = '/0';}
(二)命令的执行和实现
& 1、程序框架:
& &在对命令的解析完毕后,我们先考虑两个大的方向,即是外部命令还是内部命令?
& &外部命令的话,我们只需要fork一个子进程,用execvp()来执行就可以了;对于内部命令则需要自己去实现。
& &提出两个问题:第一个,为什么要使用execvp() ?第二个,为什么要fork一个子进程来实现,直接while循环不可以吗?
&(1)我们之所以使用execvp(),是因为函数的原型是 int execvp(const char *file ,char * const argv []); 第一个参数是命令文件名,第二个是参数,执行命令非 常的方便。
(2)一旦执行execvp(),当前进程就会被execvp的进程所替代,执行完后就会结束程序,所以while循环是不可以的,必须要fork一个子进程来执行。
while(1) { /* repeat forever */ type_prompt(); /* display prompt on the screen */ read_command(command,parameters); /* read input from terminal */ if(fork()!=0) { /* fork off child process */ /* Parent code */ waitpid(-1,&;status,0); /* wait for child to exit */ } else { /* Child code */ execvp(command,parameters); /* execute command */ }}
利用这个框架,外部命令(可执行文件)的功能基本实现(vi ,top ,ps等均可使用)。
2、输入输出重定向
当分析出来有输入输出重定向的符号时,我们要使用dup()函数来实现。函数详解请参考我的博客
对于输入的句法分析结果,我们使用一个结构体来保存:
typedef struct command{ char *args[MAXARG+1]; /* 解析出的命令参数列表 */} COMMAND;
基本流程: /* 子进程 */ if (cmd[i].infd != 0) { close(0); dup(cmd[i].infd); } if (cmd[i].outfd != 1) { close(1); dup(cmd[i].outfd); } for (j=3; j&OPEN_MAX; ++j) close(j);其中cmd[i].infd和cmd[i].outfd是解析出来的重定向位置的全局变量。3、管道命令&管道命令是使用pipe()函数实现的。关于管道的详解请参考 我的博客假如我们有 &a | b | c 这样一个形式的命令,那么是需要创建两条管道的,依次类推。 int fds[2]; for (i=0; i&cmd_ ++i) { /* 如果不是最后一条命令,则需要创建管道 */ if (i&cmd_count-1) { pipe(fds); cmd[i].outfd = fds[1]; cmd[i+1].infd = fds[0]; } forkexec(i); if ((fd = cmd[i].infd) != 0) close(fd); if ((fd = cmd[i].outfd) != 1) close(fd); } if (backgnd == 0) { /* 前台作业,需要等待管道中最后一个命令退出 */ while (wait(NULL) != lastpid) ; }4.后台作业和信号处理判断后台,我们只需要解析命令看是否存在 “&;”,若存在则backgnd = 1,不再对后台进程进行wait。为了避免僵尸进程,我们可是选择使用signal()处理SIGCHLD,将其忽略,同时忽略SIGINT和SIGQUIT信号(后台不响应ctrl+c,ctrl+z)。但是注意backgnd=0的时候要将这两个信号再设置成默认处理,否则前台也不能响应信号了。5.内部命令1、 cd命令的实现&cd命令的实现主要依赖于系统调用chdir()。我们通过将第一个参数传入chdir就可以进行一次成功的cd调用。通过判断chdir()不同的返回值可以判断出更改目录成功与否,并能输出错误原因。void do_cd(void){ get_command(0); fd=open(*(cmd[0].args),O_RDONLY); fchdir(fd); close(fd);}&2、 jobs命令的实现&jobs命令我们维护一个链表,每次当有一个后台进程运行的时候,都要向这个链表中添加一个数据。并当子进程结束的时候会向父进程发送SIGCHLD信号,父进程也就是Shell要处理这个信号,并且将后台进程链表中相应的进程进行处理,也就是将其移除。 /* 父进程 */ if (backgnd == 1) { /*添加入jobs的链表*/ NODE *p=(NODE*)malloc(sizeof(NODE)); p-&npid= printf(&%s&,cmd[0].args[0]); strcpy(p-&backcn,cmd[0].args[0]); // printf(&%s&,p-&backcn); NODE* tmp=head-& head-&next=p; p-&next= }&3、 exit命令的实现&exit命令分两部分实现。第一,当词法分析到exit的时候直接调用系统调用exit()就可以了。第二,退出之前要判断一下后台进程链表中是否还有未执行完的任务,如果有未执行完的任务,要提示用户,等待用户选择。void do_exit(void){ int Pgnum=0; NODE* tmp=head-& while(tmp!=NULL) { Pgnum++; tmp=tmp-& } if(Pgnum!=0) { printf(&There are programs in the background,are you sure to exit?y/N/n&); char c= getchar(); if(c=='N') } loop: printf(&exit/n&); exit(EXIT_SUCCESS);}4、 kill命令的实现&kill命令的实现是通过信号来实现的,我们使用kill -9 +pid来强制结束后台进程,用kill系统调用向相应的进程发送SIGQUIT信号来使进程强制退出。void do_kill(void){ get_command(0); int num=atoi(cmd[0].args[1]); signal(SIGQUIT,SIG_DFL); kill(num,SIGQUIT); signal(SIGQUIT,SIG_IGN); NODE *bng=head-& NODE *pre= while(bng!=NULL) { if(bng-&npid==num) { NODE* nxt=bng-& pre-&next= } pre= bng=bng-& }}到这里,本程序的功能已经基本实现,效果还算不错。 &注:本程序的具体源码托管至Github & ,欢迎大家关注!然而依然存在一些不足之处:1.因为时间和测试不足的关系,肯定存在着bug2.没能支持正则表达式等复杂的命令解析3.不能执行shell脚本。4.没有实现上下键查看历史命令的功能。总的来说,自己收获很大,也希望可以帮助到大家!
以上是的内容,更多
的内容,请您使用右上方搜索功能获取相关信息。
若你要投稿、删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内给你回复。
云服务器 ECS
可弹性伸缩、安全稳定、简单易用
&40.8元/月起
预测未发生的攻击
&24元/月起
邮箱低至5折
推荐购买再奖现金,最高25%
&200元/3月起
你可能还喜欢
你可能感兴趣
阿里云教程中心为您免费提供
Linux下具有基本功能的shell的具体代码实现(详细)相关信息,包括
的信息,所有Linux下具有基本功能的shell的具体代码实现(详细)相关内容均不代表阿里云的意见!投稿删除文章请联系邮箱:zixun-group@service.aliyun.com,工作人员会在五个工作日内答复
售前咨询热线
支持与服务
资源和社区
关注阿里云
International

我要回帖

更多关于 esxi shell cd命令 的文章

 

随机推荐