"outfile|command"com" />
当前位置:文档之家› Linux简单的shell实现(附源代码)

Linux简单的shell实现(附源代码)

Linux简单的shell实现(附源代码)
Linux简单的shell实现(附源代码)

Linux下Shell的实现说明文档

作业一实验要求:

Shell能够解析的语法为:

commandline := pipecommand | pipecommand "&" commandline | empty

pipecommand := redirectcommand | pipecommand "|" redirectcommand

redirectcommand := command ">" outfile |

command "<" infile |

command "<" infile ">" outfile |

command ">" outfile "<" infile |

command

command := program | command argument

1、需求说明和分析:

本作业要求为实现一个类似于bash的shell。要求支持后台命令,管道,重定向这三个基本功能。并在此基础上,实现一些简单的内部命令,例如cd,pwd等等。

2、设计方案:

1、首先利用readline()函数读到用户输入的shell命令,采用一个数组来保存shell

命令,数组有固定的大小。

2、在main()函数中根据字符串中是否存在"&" 字符判断是否为后台进程。如果是

后台命令则判断是否是多条指令,如果不是将分割后的命令传递给pipel()函数,如果是的话分割之后利用while循环将命令传递给pipel()函数。如果不是后台进

程,需要用waitpid()函数等待子进程结束后父进程才继续。

3、在pipel()函数中,将shell命令根据"|" 字符分割成一个个重定向命令,利用fork

()得到子进程,并完成管道的设置,然后对每个重定向命令调用redirect()函数(如果没有"|",则将整个shell命令调用redirect()函数)。

4、在redirect函数里面,根据有没有”>”,”<”来判断是否需要重定向。如果不需要重定

向,就直接对参数列表调用execv(char *, char **)函数执行命令。如果需要重定向,进行相应的处理,再调用execv()函数。

3、储存结构

1、帮助文档的结构,方便Help命令的构建。

struct HELP_DOC {

char *usage[lengthOfBUILTIN_COMMANDS]; //用法

char *info[lengthOfBUILTIN_COMMANDS]; //介绍

};

2、后台命令管理链表的结构,用于jobs指令的后台储存。

typedef struct BACK_JOBS {

pid_t pid;//记录进程名的pid

char *cmd;

int status;//三种状态0为DONE 1为RUNNING 2为STOPPED

}BACK_JOB;

3、History命令需要的数据的链表节点结构

typedef struct Node {

int id;

char cmd[100]; //储存每条打过的命令

struct Node *next;

} NODE;

4、shell基本功能的实现难点

1、管道的实现

管道输出核心代码为:

order = trim(strtok(cmd, "|"));

other = trim(strtok(NULL, ""));

if (!other)

redirect(order);

else {

pipe(&fd[0]);

if ((pid = fork()) == 0) {

close(fd[0]);

close(STD_OUT);

dup(fd[1]);

close(fd[1]);

redirect(order);

} else {

close(fd[1]);

close(STD_IN);

dup(fd[0]);

close(fd[0]);

waitpid(pid, &status, 0);

pipel(other);

}}

关闭管道输入端,将标准输出重定向到管道输出,然后关闭管道输出。管道输入的核心代码也是类似的。

2、输入输出重定向

首先判断是否有输入输出重定向,用标志记录,我把类型分为6种,根据这六种不同的类型,进行不同的重定向的方法。

然后在以下核心代码中实现重定向,即把标准输入输出定向到指定的文件。

if (type == 4 || type == 5 || type == 6) {

if ((fd_out = creat(outfile, 0755)) == -1) {

fprintf(stderr, "#error: redirect standard out error\n");

return -1;

}

close(STD_OUT);

dup(fd_out);

close(fd_out);

}

if (type == 3 || type == 5 || type == 6) {

if ((fd_in = open(infile, O_RDONLY, S_IRUSR | S_IWUSR)) == -1) {

fprintf(stderr, "#error: can't open inputfile '%s'\n", infile);

return -1;

}

close(STD_IN);

dup(fd_in);

close(fd_in);

}

3、后台运行的实现

后台运行相对来说比较简单,主要是利用字符处理函数,来确认cmdline中是否有’&’这个符号,如果有的话,使后台标记位为1;如果没有的话,使后台标记位为0。这样在子进程创建完毕之后,父进程通过判断后台标记位来决定是否运行wait_pid函数。这样就实现了后台运行。

4、词法分析的实现

个人觉得,在编写shell是,词法分析是一个虽然没有很大技术含量,但十分繁琐也是十分重要的环节。尤其,如果要做的完善些,处理空格,引入错误机制等。判断管道,重定向,后台命令等都是在进行词法分析,占用了很大的代码量。而这些代码又几乎都是相似的。在网上看到更加复杂的shell采用了词法分析工具来进行词法分析,这联系到了上学期所学的编译原理课程设计。而我并没有采用陈英老师提供的词法分析工具,使用了模块化的strtok 来对cmdline进行词法分析,也一样达到了很好的效果。

5、shell内部命令的实现难点

1、cd命令的实现

cd命令的实现主要依赖于系统调用chdir()。我们通过将第一个参数传入chdir就可以进行一次成功的cd调用。通过判断chdir()不同的返回值可以判断出更改目录成功与否,并能输出错误原因。

2、jobs命令的实现

jobs命令要求维护一个链表,每次当有一个后台进程运行的时候,都要向这个链表中添加一个数据。并当子进程结束的时候会向父进程发送SIGCHLD信号,父进程也就是Shell要处理这个信号,并且将后台进程链表中相应的进程进行处理。

3、exit命令的实现

exit命令分两部分实现。第一,当词法分析到exit的时候直接调用系统调用exit()就可以了。第二,退出之前要判断一下后台进程链表中是否还有未执行完的任务,如果有未执行完的任务,要提示用户,取消退出。

4、kill命令的实现

kill命令的实现是通过信号来实现的。参数就是进程的pid,利用kill系统调用可以向相应的进程发送SIGQUIT信号来使进程强制退出。

5、help命令的实现

help命令需要的文档在程序一开始运行的时候就进行初始化,当需要的时候判断help的参数,并在数组中搜索所对应的序号,打印出来即可。

6、history,!#,!-#的实现

和jobs命令类似,history也需要维护一个链表,将打过的每个命令都添加到链表里面。而!#和!-#就是对链表进行搜索,根据数字的不同,进行不同次数的溯回。

7、ctrl+z,ctrl+c的实现

两个组合键的功能比较类似,都是产生信号量。其中ctrl+c产生一个信号量,shell程序只要忽略这个信号量即可,这个信号量会自动结束子程序的。而Ctrl+z比较复杂一点,他会产生两个信号量,一个是SIGSTCP,一个是SIGCHLD。需要在这两个信号量中都作出处理。具体为shell要忽略Ctrl+z信号量,并查看这个进程时候是否以前储存在后台程序中而作出相应的添加或者忽略的处理。还有就是要及时进行状态的切换,这就要求储存后台程序的数据结构中必须有一条是程序状态。

8、bg,fg的实现

fg的实现相对来说比较简单一点,只要得到想要转到前台的进程的pid,并让shell执行waitpid即可。而bg要通过kill这个系统调用给相应pid的进程发送信号量,其中要考虑到进程状态的转换的问题。

9、左右键与上下键切换历史的实现

这个基本就是对readline库的调用,如果想实现就详细阅读一下readline库的使用方法,并无太多技术含量。

6、用户手册:

参加其他shell,基本实现了shell的基本功能。

7、编写过程遇到的问题

1、内存问题是编写shell过程中遇到的最大的问题,可能对于申请释放内存不够熟练,经常出现内存的错误。

2、信号的理解是重中之重,在和同学的讨论的过程中也发现Ctrl+z的实现是比较困难的。而没有Ctrl+z这个功能,后面的bg和fg都无法顺利的实现。

8、测试代码

dulang@ubuntu:~$ ./Shell

-------------*Welcome*-------------

dulang:~$ls

abc out.c shell0.9.c shellproblem 公共的文档

examples.desktop out.txt Shell1 shellPS.c 模板下载

in shell shell.c test 视频音乐

out Shell Shell.c workspace 图片桌面

dulang:~$ls >abc

abc

examples.desktop

in

out

out.c

out.txt

shell

Shell

shell0.9.c

Shell1

shell.c

Shell.c

shellproblem

shellPS.c

test

workspace

公共的

模板

视频

图片

文档

下载

音乐

桌面

dulang:~$ls |grep shell|grep .c

shell0.9.c

shell.c

shellPS.c

dulang:~$ls |grep shell|grep .c >abcd dulang:~$cat abcd

shell0.9.c

shell.c

shellPS.c

dulang:~$cd Shell

#error: this is not a directory name

dulang:~$cd workspace

dulang:/home/dulang/workspace$cd .. dulang:~$sleep 5&

[1] 5255 RUNNING sleep 5 dulang:~$jobs

[1] 5255 RUNNING sleep 5 dulang:~$jobs

[1] 5255 DONE sleep 5

^Z

[2] 5260 STOPPED This is a stop process. dulang:~$jobs

[1] 5255 DONE sleep 5

[2] 5260 STOPPED This is a stop process. dulang:~$fg 1

dulang:~$fg 2

dulang:~$jobs

[1] 5255 DONE sleep 5

[2] 5260 DONE This is a stop process. dulang:~$history

id:18 history

id:17 jobs

id:16 fg 2

id:15 fg 1

id:14 jobs

id:13 sleep 10

id:12 jobs

id:11 jobs

id:10 sleep 5&

id:9 cd ..

id:8 cd workspace

id:7 cd Shell

id:6 cat abcd

id:5 ls |grep shell|grep .c >abcd

id:4 ls |grep shell|grep .c

id:3 cat abc

id:2 ls >abc

id:1 ls

dulang:~$!-1

id:18 history

id:17 jobs

id:16 fg 2

id:15 fg 1

id:14 jobs

id:13 sleep 10

id:12 jobs

id:11 jobs

id:10 sleep 5&

id:9 cd ..

id:8 cd workspace

id:7 cd Shell

id:6 cat abcd

id:5 ls |grep shell|grep .c >abcd

id:4 ls |grep shell|grep .c

id:3 cat abc

id:2 ls >abc

id:1 ls

dulang:~$!1

abc out Shell Shell.c workspace 图片桌面

abcd out.c shell0.9.c shellproblem 公共的文档

examples.desktop out.txt Shell1 shellPS.c 模板下载

in shell shell.c test 视频音乐

dulang:~$pwd

/home/dulang

dulang:~$

10、附录(源程序):

====================================================================== ======

11、Name : Shell.c

12、Author : Dulang

13、Version :

14、Copyright : dulang @ copyright notice

15、Description : Shell in C, Ansi-style

16、

====================================================================== ======

17、*/

18、

19、#include

20、#include

21、#include

22、#include

23、#include

24、#include

25、#include

26、#include

27、#include

28、#include

29、#include

30、#include

31、#include

32、#define STD_IN 0

33、#define STD_OUT 1

34、#define MAXORD 20

35、#define MAXPARA 8

36、#define MAX_BACK_JOBS_NUM 20

37、#define SIGSTCP 20

38、#define lengthOfBUILTIN_COMMANDS 10

39、

40、s tatic int back_jobs_ptr = 0;

41、c har *st[] = { "DONE", "RUNNING", "STOPPED" };

42、i nt currentpid;//记录当前shell运行的pid.

43、i nt isCtrlz;

44、e num BUILTIN_COMMANDS { NO_SUCH_BUILTIN=0, EXIT, CD, HISTORY,

DO_HIS_CMD, PWD, KILL, HELP, JOBS };

45、//for tab completion

46、c har *commands[] = {"cd", "cp", "chmod",

47、"exit",

48、"mv", "man"

49、"rm", "rmdir",

50、"vi", "bg","fg","grep","ls","cat",

51、"history", "help",

52、"jobs", "kill"

53、"ps", "pwd"};

54、

55、s truct HELP_DOC {

56、char *usage[lengthOfBUILTIN_COMMANDS];

57、char *info[lengthOfBUILTIN_COMMANDS];

58、};

59、c har *trim(const char *str);

60、i nt is_back(char *order);

61、i nt pipel(char *cmd);

62、c har *if_exist(char *order);

63、v oid handle_sigchld(int s);

64、v oid handle_sigint(int s);

65、v oid handle_sigstcp(int s);

66、v oid initWithHelpDoc(struct HELP_DOC*);

67、v oid do_help(char *);

68、v oid do_pwd();

69、//后台进程

70、t ypedef struct BACK_JOBS {

71、pid_t pid;

72、char *cmd;

73、int status;

74、}BACK_JOB;

75、

76、t ypedef struct Node {

77、int id;

78、char cmd[100];

79、struct Node *next;

80、}NODE;

81、

82、s truct BACK_JOBS *back_jobs[MAX_BACK_JOBS_NUM];

83、s tatic NODE *head;

84、s truct HELP_DOC * help_doc;

85、

86、i nt pipel(char *cmd) {

87、char *trim(const char *str);

88、int redirect(char *cmd);

89、

90、int fd[2], status, pid;

91、char *order, *other;

92、order = trim(strtok(cmd, "|"));

93、other = trim(strtok(NULL, ""));

94、if (!other)

95、redirect(order);

96、else {

97、pipe(&fd[0]);

98、if ((pid = fork()) == 0) {

99、close(fd[0]);

100、close(STD_OUT);

101、dup(fd[1]);

102、close(fd[1]);

103、redirect(order);

104、} else {

105、close(fd[1]);

106、close(STD_IN);

107、dup(fd[0]);

108、close(fd[0]);

109、waitpid(pid, &status, 0);

110、pipel(other);

111、}

112、}

113、return 1;

114、}

115、

116、int redirect(char *cmd) {

117、char *trim(const char *str);

118、void do_cd(char *argv[]);

119、

120、char *order = trim(cmd), *order_path, *real_order; 121、char *infile, *outfile, *arg[MAXPARA], *buffer;

122、int i, type = 2, fd_out, fd_in;

123、

124、for (i = 0; i < strlen(cmd); i++) {

125、if (cmd[i] == '<')

126、type++;

127、if (cmd[i] == '>')

128、type = type * 2;

129、}

130、if (type == 3 || type == 6)

131、real_order = trim(strtok(cmd, "<"));

132、else if (type == 4 || type == 5)

133、real_order = trim(strtok(cmd, ">"));

134、else if (type == 2)

135、real_order = trim(cmd);

136、else {

137、fprintf(stderr, "#error: bad redirection form\n");

138、return -1;

139、}

140、

141、arg[0] = trim(strtok(real_order, " "));

142、for (i = 1; (arg[i] = trim(strtok(NULL, " "))) != NULL; i++)

143、;

144、if (strcmp(arg[0], "history") == 0) {

145、while (head->next != NULL) {

146、printf("id:%d %s\n", head->id, head->cmd); 147、head = head->next;

148、}

149、exit(1);

150、return 1;

151、}

152、if (strcmp(arg[0], "jobs") == 0) {

153、int i = 1;

154、for (; i < MAX_BACK_JOBS_NUM; i++) {

155、if (back_jobs[i] != NULL)

156、printf("[%d] %d %s\t\t\t\t%s\n", i, back_jobs[i]->pid, 157、st[back_jobs[i]->status], back_jobs[i]->cmd); 158、}

159、exit(1);

160、return 1;

161、}

162、if (strcmp(arg[0], "help") == 0) {

163、do_help(arg[1]);

164、exit(1);

165、return 1;

167、if (strcmp(arg[0], "pwd") == 0) {

168、do_pwd();

169、exit(1);

170、return 1;

171、}

172、if ((order_path = if_exist(arg[0])) == NULL) {

173、fprintf(stderr, "#error: this command doesn't exist\n"); 174、exit(1);

175、return -1;

176、}

177、switch (type) {

178、case 2:

179、break;

180、case 3:

181、buffer = strtok(order, "<");

182、infile = trim(strtok(NULL, ""));

183、break;

184、case 4:

185、buffer = strtok(order, ">");

186、outfile = trim(strtok(NULL, ""));

187、break;

188、case 5:

189、buffer = strtok(order, ">");

190、outfile = trim(strtok(NULL, "<"));

191、infile = trim(strtok(NULL, ""));

192、break;

193、case 6:

194、buffer = strtok(order, "<");

195、infile = trim(strtok(NULL, ">"));

196、outfile = trim(strtok(NULL, ""));

197、break;

198、default:

199、return -1;

200、}

201、

202、if (type == 4 || type == 5 || type == 6) {

203、if ((fd_out = creat(outfile, 0755)) == -1) {

204、fprintf(stderr, "#error: redirect standard out error\n"); 205、return -1;

206、}

207、close(STD_OUT);

208、dup(fd_out);

209、close(fd_out);

211、

212、if (type == 3 || type == 5 || type == 6) {

213、if ((fd_in = open(infile, O_RDONLY, S_IRUSR | S_IWUSR)) == -1) { 214、fprintf(stderr, "#error: can't open inputfile '%s'\n", infile);

215、return -1;

216、}

217、close(STD_IN);

218、dup(fd_in);

219、close(fd_in);

220、}

221、execv(order_path, arg);

222、

223、exit(0);

224、return 1;

225、}

226、

227、int is_back(char *order) {

228、int len = strlen(order);

229、if (order[len - 1] == '&') {

230、order[len] = '\0';

231、return 1;

232、} else

233、return 0;

234、}

235、

236、void do_cd(char *argv[]) {

237、if (argv[1] != NULL) {

238、if (chdir(argv[1]) < 0) {

239、switch (errno) {

240、case ENOENT:

241、fprintf(stderr, "#error: directory can't be found\n");

242、break;

243、case ENOTDIR:

244、fprintf(stderr, "#error: this is not a directory name\n"); 245、break;

246、case EACCES:

247、fprintf(stderr, "#error: you have no right to access\n"); 248、break;

249、default:

250、fprintf(stderr, "#error: unknown error\n");

251、}

252、}

253、}

254、}

255、

256、void do_help(char *argv){

257、int i;

258、if(argv==NULL){

259、i=HELP;

260、}

261、else if(strcmp(argv,"cd")==0){

262、i=CD;

263、}else if(strcmp(argv,"exit")==0){

264、i=EXIT;

265、}else if(strcmp(argv,"history")==0){

266、i=HISTORY;

267、}else if(strcmp(argv,"pwd")==0){

268、i=PWD;

269、}else if(strcmp(argv,"help")==0){

270、i=HELP;

271、}else if(strcmp(argv,"jobs")==0){

272、i=JOBS;

273、}

274、printf("%s\n",help_doc->usage[i]);

275、printf("%s\n",help_doc->info[i]);

276、return;

277、}

278、

279、char *if_exist(char *order) {

280、char *all_path, *p, *path, *buffer;

281、int len;

282、all_path = getenv("PATH");

283、buffer = trim(all_path);

284、len = strlen(all_path) + strlen(order);

285、if ((path = (char *) malloc(len * (sizeof(char)))) == 0) {

286、fprintf(stderr, "#error: can't malloc enough space for buffer\n"); 287、return NULL;

288、}

289、p = strtok(buffer, ":");

290、while (p) {

291、strcat(strcat(strcpy(path, p), "/"), order);

292、if (access(path, F_OK) == 0) {

293、return path;

294、}

295、p = strtok(NULL, ":");

296、}

297、strcpy(path, order);

298、if (access(path, F_OK) == 0)

299、return path;

300、return NULL;

301、}

302、

303、char *trim(const char *str) {

304、int i, j, k;

305、char *order;

306、if (str == NULL)

307、return NULL;

308、for (i = 0; i < strlen(str); i++)

309、if (str[i] != ' ' && str[i] != ' ')

310、break;

311、for (j = strlen(str) - 1; j > -1; j--)

312、if (str[j] != ' ' && str[j] != ' ')

313、break;

314、if (i <= j) {

315、if ((order = (char *) malloc((j - i + 2) * (sizeof(char)))) == 0) { 316、fprintf(stderr, "#error: can't malloc enough space\n"); 317、return NULL;

318、}

319、for (k = 0; k < j - i + 1; k++)

320、order[k] = str[k + i];

321、order[k] = '\0';

322、return order;

323、} else

324、return NULL;

325、}

326、

327、void handle_sigchld(int s) {

328、/* execute non-blocking waitpid, loop because we may only receive 329、* a single signal if multiple processes exit around the same time. 330、*/

331、// printf("recieve %d pid %d.\n",s,currentpid);

332、

333、int i=1;

334、if(isCtrlz==0)

335、{

336、for (; i < MAX_BACK_JOBS_NUM; i++) {

337、if (back_jobs[i] == NULL)

338、continue;

339、if (back_jobs[i]->pid == currentpid) {

340、back_jobs[i]->status = 0;

341、break;

342、}

343、}

344、}else{

345、isCtrlz=0;

346、}

347、pid_t pid;

348、while ((pid = waitpid(0, NULL, WNOHANG)) > 0) {

349、int i = 1;

350、for (; i < MAX_BACK_JOBS_NUM; i++) {

351、if (back_jobs[i] == NULL)

352、continue;

353、if (back_jobs[i]->pid == pid) {

354、back_jobs[i]->status = 0;

355、break;

356、}

357、}

358、}

359、}

360、

361、void handle_sigint(int s) {

362、//printf("A sigint receive.");

363、return;

364、}

365、

366、void handle_sigstcp(int s) {

367、int i = 1;

368、isCtrlz=1;//告诉另一个信号处理函数,这是一个ctrlz

369、int flag=0;//如果等于0,则代表这个程序没有被后台过。370、printf("\n");

371、// kill(currentpid,SIGSTCP);

372、for (; i < MAX_BACK_JOBS_NUM; i++) {

373、if (back_jobs[i] == NULL)

374、continue;

375、if (back_jobs[i]->pid == currentpid) {

376、back_jobs[i]->status = 2;

377、flag=1;

378、break;

379、}

380、}

381、

382、if(flag==0){

383、back_jobs_ptr++;

384、back_jobs[back_jobs_ptr] = (struct BACK_JOBS *) malloc( 385、sizeof(struct BACK_JOBS *));

386、back_jobs[back_jobs_ptr]->pid = currentpid;

387、back_jobs[back_jobs_ptr]->cmd = (char *) malloc(100);

388、strcpy(back_jobs[back_jobs_ptr]->cmd, "This is a stop process."); 389、back_jobs[back_jobs_ptr]->status = 2;

390、printf("[%d] %d %s\t\t\t\t%s\n", back_jobs_ptr,

391、back_jobs[back_jobs_ptr]->pid,

392、st[back_jobs[back_jobs_ptr]->status],

393、back_jobs[back_jobs_ptr]->cmd);

394、}

395、return;

396、}

397、

398、void initWithHelpDoc(struct HELP_DOC *help_doc) {

399、help_doc->usage[EXIT] = "exit: exit";

400、help_doc->info[EXIT] = "Exit the shell.";

401、

402、help_doc->usage[CD] = "cd: cd [dir]";

403、help_doc->info[CD] =

404、"Change the shell working directory.\

405、\n\tChange the current directory to DIR.\

406、\n\tThe default DIR is the value of the HOME shell variable.";

407、

408、help_doc->usage[HISTORY] = "history: history [-c] [-s num]";

409、help_doc->info[HISTORY] =

410、"Display or manipulate the history list.\

411、\n\tDisplay the history list with line numbers, prefixing each modified\ 412、\n\tentry with a `*'. An argument of N lists only the last N entries.\

413、\n\

414、\n\tOptions:\

415、\n\t -c\t\tclear the history list by deleting all of the entries\

416、\n\t -s num\tsize of the history buffer to num";

417、

418、help_doc->usage[PWD] = "pwd: pwd";

419、help_doc->info[PWD] = "Print the name of the current working directory."; 420、

421、help_doc->usage[HELP] = "help: help [pattern ...]";

422、help_doc->info[HELP] =

423、"Display information about builtin commands.\

424、\n\tArguments:\

425、\n\t PATTERN Pattern specifiying a help topic";

426、

427、help_doc->usage[JOBS] = "jobs: jobs";

428、help_doc->info[JOBS] =

429、"Display status of jobs.\

430、\n\tLists the active jobs. JOBSPEC restricts output to that job.";

431、}

432、

433、void do_pwd() {

434、char dirname[100];

435、if(getcwd(dirname, 99) == NULL) {

436、fprintf(stderr,"getcwd error\n");

437、}

438、else {

439、printf("%s \n",dirname);

440、}

441、}

442、char *command_generator(const char *text, int state) {

443、char *name;

444、static int list_index, len;

445、

446、if (!state) {

447、list_index = 0;

448、len = strlen (text);

449、}

450、

451、while (name = commands[list_index]) {

452、list_index++;

453、

454、if (strncmp(name, text, len) == 0)

455、return (strdup(name));

456、}

457、

458、return ((char *)NULL);

459、}

460、

461、

462、char **command_completion(const char *text, int start, int end) {

463、char **matches = NULL;

464、

465、if (start == 0)

466、matches = rl_completion_matches(text, command_generator);

467、

468、return (matches);

469、}

470、

471、void initialize_readline() {

472、rl_attempted_completion_function = (CPPFunction *)command_completion; 473、

474、}

475、

476、int main(void) {

477、signal(SIGCHLD, handle_sigchld);

478、signal(SIGINT,handle_sigint);

479、signal(SIGSTCP,handle_sigstcp);

480、

481、char all_order[100], *order[MAXORD];

482、int i, pid, status, number = 1, back, historyid = 1;

483、char buf[80],prompt[100];

484、char tmp[80];

485、memset(tmp, 0, sizeof(tmp));

486、char *username, *arg[MAXPARA];

487、struct group *data;

488、

489、head = (NODE*) malloc(sizeof(NODE));

490、strcat(head->cmd, "intial");

491、data = getgrgid(getgid());

492、username = data->gr_name;

493、strcat(tmp, "/home/");

494、strcat(tmp, username);

495、

496、//help 文档

497、help_doc = (struct HELP_DOC *)malloc(20*sizeof(struct HELP_DOC *)); 498、initialize_readline();

499、initWithHelpDoc(help_doc);

500、printf("-------------*Welcome*-------------\n");

501、while (1) {

502、getcwd(buf, sizeof(buf));

503、if (strcmp(tmp, buf) == 0) {

504、memset(buf, 0, sizeof(buf));

505、buf[0] = '~';

506、buf[1] = '\0';

507、}

508、sprintf(prompt,"%s:%s$", username, buf);

509、// printf("%s",prompt);

510、// strcat(prompt,username);

511、// strcat(prompt,":");

512、// strcat(prompt,buf);

513、// strcat(prompt,"$");

514、// printf("%s",prompt);

515、

516、//fgets(all_order,sizeof(all_order),stdin);

517、// gets(all_order);

518、char *t;

519、t=readline(prompt);

520、sprintf(all_order,"%s", t);

521、if (all_order == NULL || trim(all_order) == NULL)

522、continue;

523、//储存历史命令

524、NODE *next;

525、next = (NODE*) malloc(sizeof(NODE));

526、next->id = historyid++;

527、strcpy(next->cmd, trim(all_order));

528、next->next = head;

529、head = next;

530、add_history(all_order);

531、

532、back = is_back(trim(all_order));

533、if (strcmp(trim(all_order), "exit") == 0) {

534、int i = 1;

535、int e = 1;

536、for (; i < MAX_BACK_JOBS_NUM; i++) {

537、if (back_jobs[i] != NULL) {

538、if (back_jobs[i]->status != 0) {

539、 e = 0;

540、break;

541、}

542、}

543、

544、}

545、if (e == 0) {

546、fprintf(stdout,

547、"Some jobs are undone, please stop them first.\n"); 548、fprintf(stdout, "Type \"jobs\" to see them.\n");

549、continue;

550、} else {

551、printf("-------------*Goodbye*-------------\n");

552、exit(-1);

553、}

554、}

555、if (trim(all_order)[0] == '!'&&trim(all_order)[1]=='-') {

556、int i;

557、sscanf(trim(all_order), "!-%d", &i);

558、if(i<0) fprintf(stderr,"!# # must be a negative number.");

559、NODE* p;

560、p=head;

561、int j,flag=0;

562、for(j=0;j

563、p=p->next;

564、if(p==NULL){

565、fprintf(stderr,"!# # must be a less than history number."); 566、flag=1;

567、}

568、}

569、if(flag==1) continue;

570、strcpy(all_order,p->cmd);

571、historyid=historyid-1;

572、head=head->next;

573、}else if(trim(all_order)[0] == '!'){

574、int i;

575、sscanf(trim(all_order), "!%d", &i);

576、if(i<0) fprintf(stderr,"!# # must be a negative number.");

577、i=historyid-i-1;

578、NODE* p;

579、p=head;

580、int j,flag=0;

581、for(j=0;j

582、p=p->next;

583、if(p==NULL){

584、fprintf(stderr,"!# # must be a less than history number."); 585、flag=1;

586、}

587、}

588、if(flag==1) continue;

589、strcpy(all_order,p->cmd);

590、historyid=historyid-1;

591、head=head->next;

592、}

593、if(trim(all_order)[0]=='f'&&trim(all_order)[1]=='g'){

594、int i;

595、sscanf(trim(all_order), "fg%d", &i);

596、if(back_jobs[i]->status==0){

597、continue;

598、}

599、currentpid=back_jobs[i]->pid;

600、kill(back_jobs[i]->pid,SIGCONT);

601、back_jobs[i]->status=1;

602、waitpid(back_jobs[i]->pid, &status, WUNTRACED);

603、continue;

604、}

605、

linux+shell脚本语言基础知识

linux shell脚本语言基础知识 一.shell简介 Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的界面,更确切的说,shell是用户与Linux操作系统沟通的桥梁。用户既可以输入命令执行,又可以利用Shell脚本编程,完成更加复杂的操作。 shell是一个命令解释器,它从输入设备读取命令,再将其转为计算机可以了解的指令,然后执行它。在linux中,shell又不仅是简单的命令解释器,而且是一个全功能的编程环境。 Linux的Shell种类众多,常见的有:Bourne Shell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、C Shell(/usr/bin/csh)、K Shell (/usr/bin/ksh)、Shell for Root(/sbin/sh),等等。不同的Shell语言的语法有所不同,所以不能交换使用。每种Shell都有其特色之处,基本上,掌握其中任何一种就足够了。通常用Bash,也就是Bourne Again Shell进行编程。 二.shell使用 1.建立和运行shell程序 shell脚本程序:按照一定的语法结构把若干linux命令组织在一起,是这些命令按照我们的要求完成一定的功能。它可以进行类似程序的编写,并且不需要编译就能执行。(只需修改其权限) 像编写高级语言的程序一样,编写shell程序需要一个文本编辑器,如VI和VIM,通常使用VIM文本编辑器,支持更便利的插入模式。 首先使用VIM编辑器编辑一个hello.sh文件: #!/bin/bash #hello world example

经典shell 脚本实例

Linux shell 脚本实例 1. 写一个脚本,利用循环计算10的阶乘#!/bin/sh factorial=1 for a in `seq 1 10` do factorial=`expr $factorial \* $a` done echo "10! = $factorial" 2. 写一个脚本,执行后,打印一行提示“Please input a number:",要求用户输入数值,然后打印出该数值,然后再次要求用户输入数值。直到用户输入"end"停止。#!/bin/sh unset var while [ "$var" != "end" ] do echo -n "please input a number: " read var if [ "$var" = "end" ] then break fi echo "var is $var" done ////////////////////////////////////////// #!/bin/sh unset var while [ "$var" != "end" ] do echo -n "please input a number: " read var if [ "$var" = "end" ] then break fi echo "var is $var" done 3. 写一个脚本,利用循环和continue关键字,计算100以内能被3整除的数之和 4.一个函数,利用shift计算所有参数乘积,假设参数均为整数 #! /bin/sh result=1 while [ $# -gt 0 ] do result=`expr $result * $1` shift done echo $result 5.写一个脚本,可以根据参数文件名,以正确的参数调用tar来解压缩tar.gz或tar.bz2文件。#!/bin/shcase ${1##*.tar.} in bz2) tar jxvf $1 ;; gz) tar zxvf $1 ;; *) echo "wrong file type"esac6.写一个脚本以方便用户查询rpm的相关信息。这个脚本首先提示用户选择查询依据,比如文件名,包名,全部等。然后提示用户选择查询信息,比如包名,包里所包含的所有文件,包的信息等。然后询问是否继续查询,是则循环刚才的过程,否则退出。

Shell脚本编程详解-吐血共享

第12章 Shell 脚本编程 ● Shell 命令行的运行 ● 编写、修改权限和执行Shell 程序的步骤 ● 在Shell 程序中使用参数和变量 ● 表达式比较、循环结构语句和条件结构语句 ● 在Shell 程序中使用函数和调用其他Shell 程序 12-1 Shell 命令行书写规则 ◆ Shell 命令行的书写规则 对Shell 命令行基本功能的理解有助于编写更好的Shell 程序,在执行Shell 命令时多个命令可以在一个命令行上运行,但此时要使用分号(;)分隔命令,例如: [root@localhost root]# ls a* -l;free;df 长Shell 命令行可以使用反斜线字符(\)在命令行上扩充,例如: [root@localhost root]# echo “ this is \ >long command ” This is long command 注意: “>”符号是自动产生的,而不是输入的。 12-2 编写/修改权限及执行Shell 程序的步骤 ◆ 编写Shell 程序 ◆ 执行Shell 程序 Shell 程序有很多类似C 语言和其他程序设计语言的特征,但是又没有程序语言那样复杂。Shell 程序是指放在一个文件中的一系列Linux 命令和实用程序。在执行的时候,通过Linux 操作系统一个接一个地解释和执行每条命令。首先,来编写第一个Shell 程序,从中学习Shell 程序的编写、修改权限、执行过程。

12-2-1 编辑Shell程序 编辑一个内容如下的源程序,保存文件名为date,可将其存放在目录/bin下。 [root@localhost bin]#vi date #! /bin/sh echo “Mr.$USER,Today is:” echo &date “+%B%d%A” echo “Wish you a lucky day !” 注意: #! /bin/sh通知采用Bash解释。如果在echo语句中执行Shell命令date,则需要在date 命令前加符号“&”,其中%B%d%A为输入格式控制符。 12-2-2 建立可执行程序 编辑完该文件之后不能立即执行该文件,需给文件设置可执行程序权限。使用如下命令。[root@localhost bin]#chmod +x date 12-2-3 执行Shell程序 执行Shell程序有下面三种方法: 方法一: [root@localhost bin]#./ date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day ! 方法二: 另一种执行date的方法就是把它作为一个参数传递给Shell命令: [root@localhost bin]# Bash date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day ! 方法三: 为了在任何目录都可以编译和执行Shell所编写的程序,即把/bin的这个目录添加到整个环境变量中。 具体操作如下: [root@localhost root]#export PATH=/bin:$PATH [root@localhost bin]# date Mr.root,Today is: 二月 06 星期二 Wish you a lucky day !

LinuxShell脚本教程(一):Shell入门

LinuxShell脚本教程(一):Shell入门 LinuxShell脚本教程(一):Shell入门 在这里我们介绍的是Bashshell(BourneAgainShell),它是目前大多数GUN/Linux系统默认的shell环境。书中所有的实验都是在Ubuntu14.04LTS环境下完成的。 在ubuntu14.04LTS系统中,已经默认安装了一个Terminal,我们可以通过多种方法打开终端。这里介绍两种: 方法一:通过系统自带的检索系统,我们可以轻松找到终端(Terminal),单击即可打开。检索系统可以通过快速启动栏右上角的按钮启动。 方法二:为了之后可以方便的打开终端,建议将终端固定在快速启动栏。操作方法为:通过方法一打开终端后,快速启动栏会出现一个终端的图表,在图表上单击鼠标右键,选择“固定在启动栏”即可将终端固定在快速启动栏。 默认情况下,终端提示符为:username@hostname或者 root@hostname#。代表普通用户,#代表root用户。 例如:我在打开终端后,提示符为:wxb@ubuntu:~$。 root是linux系统中权限最高的用户,能力大风险也大,因此不介意使用root用户作为登陆系统的.默认用户。 通常情况下,对于个人版linux操作系统,系统上会存在两个用户,即用户自己以及root用户。对于使用者来说,时有需要切换用户,以执行一些普通用户不能执行的操作,此处提供两种方法切换用户。 方法一:临时切换。顾名思义,这种切换方法仅仅是临时的,当指令执行完成后,就会切换到原来的用户。切换指令为:sudocommand,sudo是superuserdo的简写。

linux操作系统之Shell编程

shell1.sh 显示日期和时间。 #!/bin/bash echo “current time is `date`” //date要加反引号 shell2.sh 显示文件名,并显示位置参数(执行时带一个参数)。(①$0是一个特殊的变量,它的内容是当前这个shell程序的文件名;②$1是一个位置参数,位置参数之间用空格分隔,shell取第一个位置参数替换程序文件中的$1,第二个替换$2,依次类推。) #!/bin/bash echo “the program name is $0” //$0是一个特殊的变数 echo “the first para is $1” //$1是一个位置参数 echo “the program exit” //执行时带一个参数如./shell2.sh abcd shell3.sh 判断并显示位置参数 #!/bin/bash if [ -d “$1”];then echo “$1 is directory ,existed” else echo “$1 does not exist ,now create it” mkdir $1 echo “$1 is created” fi //执行时带一个参数 shell4.sh 问候用户 #!/bin/bash user=`whoami` case $user in teacher) echo “hello teacher”;; root) echo “hello root”;; *) echo “hello $user,welcome” esac 1、求1+2+3+...+100的和是? #!/bin/bash

linux Shell(脚本)编程入门 实例讲解详解

linux Shell(脚本)编程入门实例讲解详解 为什么要进行shell编程 在Linux系统中,虽然有各种各样的图形化接口工具,但是sell仍然是一个非常灵活的工具。Shell不仅仅是命令的收集,而且是一门非常棒的编程语言。您可以通过使用shell使大量的任务自动化,shell特别擅长系统管理任务,尤其适合那些易用性、可维护性和便携性比效率更重要的任务。 下面,让我们一起来看看shell是如何工作的: 建立一个脚本 Linux中有好多中不同的shell,但是通常我们使用bash (bourne again shell) 进行shell编程,因为bash是免费的并且很容易使用。所以在本文中笔者所提供的脚本都是使用bash(但是在大多数情况下,这些脚本同样可以在bash 的大姐,bourne shell中运行)。 如同其他语言一样,通过我们使用任意一种文字编辑器,比如nedit、kedit、emacs、vi等来编写我们的shell程序。程序必须以下面的行开始(必须方在文件的第一行): 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。当编辑好脚本时,如果要执行该脚本,还必须使其可执行。 要使脚本可执行: 然后,您可以通过输入: ./filename 来执行您的脚本。 注释 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。 变量 在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写:

linux的shell技巧(很实用)

引言 Shell作为Unix系操作系统当中最有魅力且不可或缺的组件,经过数十载的洗礼不仅没有被淘汰,而且愈加变得成熟稳健,究其原因,大概因为它是个非常稳固的粘合剂,能够把大量功能强大的组件任意配搭,总能很好很快地完成用户的任务。 1.以sudo运行上条命令 $sudo!! 大家应该都知sudo,不解释。但通常出现的情况是,敲完命令执行后报错才发现忘了sudo。这时候,新手用户就会:按上箭头,按左箭头,盯着光标回到开始处,输入sudo,回车;高手用户就蛋定多了,按Ctrl-p,按Ctrl-a,输入sudo,回车。 这里介绍这个是天外飞仙级别的,对,就直接sudo!!。 当然这几种解决方式效果是完全一样的,只是款不一样,嗯,不解释。 两个感叹号其实是bash的一个特性,称为事件引用符(event designators)。!!其实相当于!-1,引用前一条命令,当然也可以!-2,!-50。默认情况下bash会在~/.bash_history文件内记录用户执行的最近500条命令,history命令可以显示这些命令。 关于事件引用符的更多用法可以深入阅读The Definitive Guide to Bash Command Line History。 2.以HTTP方式共享当前文件夹的文件 $python-m SimpleHTTPServer 这命令启动了Python的SimpleHTTPServer模块,考虑到Python在绝大多数的Linux发行版当中都默认安装,所以这个命令很可能是最简单的跨平台传文件的方法。 命令执行后将在本机8000端口开放HTTP服务,在其他能访问本机的机器的浏览器打开ttp://ip:8000即打开一个目录列表,点击即可下载。 3.在以普通用户打开的vim当中保存一个root用户文件 :w!sudo tee% 这题目读起来纠结,其实是很常见的,常常忘记了sudo就直接用vim编辑/ etc内的文件,(不过也不一定,vim发现保存的文件无法保存时候会提示)等

Shell编程基础教程

1. Linux 脚本编写基础 1.1 语法基本介绍 1.1.1 开头 程序必须以下面的行开始(必须放在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序。在这个例子中我们使用/bin/sh来执行程序。 当编辑好脚本时,如果要执行该脚本,还必须使其可执行。要使脚本可执行: chmod +x filename 这样才能用./filename 来运行 1.1.2 注释 在进行shell编程时,以#开头的句子表示注释,直到这一行的结束。我们真诚地建议您在程序中使用注释。如果您使用了注释,那么即使相当长的时间内没有使用该脚本,您也能在很短的时间内明白该脚本的作用及工作原理。 1.1.3 变量 在其他编程语言中您必须使用变量。在shell编程中,所有的变量都由字符串组成,并且您不需要对变量进行声明。要赋值给一个变量,您可以这样写: #!/bin/sh #对变量赋值: a="hello world" # 现在打印变量a的内容: echo "A is:" echo $a 有时候变量名很容易与其他文字混淆,比如: num=2 echo "this is the $numnd" 这并不会打印出"this is the 2nd",而仅仅打印"this is the ",因为shell会去搜索变量numnd的值,但是这个变量时没有值的。可以使用花括号来告诉shell我们要打印的是num变量: num=2 echo "this is the ${num}nd"

这将打印: this is the 2nd 1.1.4 环境变量 由export关键字处理过的变量叫做环境变量。我们不对环境变量进行讨论,因为通常情况下仅仅在登录脚本中使用环境变量。 1.1.5 Shell命令和流程控制 在shell脚本中可以使用三类命令: 1)Unix 命令: s虽然在shell脚本中可以使用任意的unix命令,但是还是由一些相对更常用的命令。这些命令通常是用来进行文件和文字操作的。 常用命令语法及功能: echo "some text": 将文字内容打印在屏幕上 ls: 文件列表 wc –l filewc -w filewc -c file: 计算文件行数计算文件中的单词数计算文件中的字符数 cp sourcefile destfile: 文件拷贝 mv oldname newname : 重命名文件或移动文件 rm file: 删除文件 grep 'pattern' file: 在文件内搜索字符串比如:grep 'searchstring' file.txt cut -b colnum file: 指定欲显示的文件内容范围,并将它们输出到标准输出设备比如:输出每行第5个到第9个字符cut -b5-9 file.txt千万不要和cat命令混淆,这是两个完全不同的命令 cat file.txt: 输出文件内容到标准输出设备(屏幕)上 file somefile: 得到文件类型 read var: 提示用户输入,并将输入赋值给变量 sort file.txt: 对file.txt文件中的行进行排序 uniq: 删除文本文件中出现的行列比如: sort file.txt | uniq expr: 进行数学运算Example: add 2 and 3expr 2 "+" 3 find: 搜索文件比如:根据文件名搜索find . -name filename -print tee: 将数据输出到标准输出设备(屏幕) 和文件比如:somecommand | tee outfile basename file: 返回不包含路径的文件名比如: basename /bin/tux将返回 tux

Linux下最常用的Shell命令的介绍

有些人仍然会有这种愚蠢的想法,他们认为使用Linux就必须使用Linux shell命令。胡说!你可以不懂得任何Linux命令,比如说ps,grep,ls等,但是你仍然可以使用很多现代的Linux桌面发行版。 Linux的系统管理员与桌面用户不一样,他们不像桌面用户一样使用Cinnamon,GNOME,Unity,或者KDE,他们所有的时间都是用Linux命令。 对于桌面用户来讲,若是了解一部分Linux命令,你可以更好的使用Linux,体验它的魅力,下面列举出了一些: Shell基础: 你可以通过打开Linux的terminal(终端)来执行Shell命令。Shell的种类有很多种,例如CSH,Bourne Shell,Korn Shell。在现在的大多数Linux发行版中,默认的Shell一般都是Bourne again shell(bash)。 想看看你的Shell是哪一种,执行下面的命令 echo $SHELL 在Linux中,$符号代表一个shell变量。所有的shell都用这种方式使用变量。有一些shell 变量在你的系统启动的时候就有了默认值。例如,$SHELL;$LOGNAME是你的登录名,而$PATH变量指明了你的shell命令的搜索范围。 echo命令的作用就是打印出你的输入。如果你的输入具有shell的特殊意义,例如shell变量,他就输出变量的值。 一个重要的地方是,你要注意文本的大小写。例如,ls,是DOS的dir命令的Linux版本。这个命令列出当前工作目录下的文件列表。如果你输入的是LS,你得到的只能是“找不到命令”的错误信息。 另外在Linux shell命令中一个重要的地方是,你可以将命令串起来。这是Unix/Linux从第一天开始就有的巧妙的特点。最简单的将命令连起来的办法就是使用“|”,我们称之为“pipe”。第一个命令的输出就是下一个命令的输入。 Linux命令有自己的语法规则: 基本的语法就像这样: command -option file 例如:

shell脚本实例

shell脚本实例 1. 写一个脚本,利用循环计算10的阶乘 #!/bin/sh factorial=1 for a in `seq 1 10` do factorial=`expr $factorial \* $a` done echo "10! = $factorial" 注:上面有一行,for a in `seq 1 10`,其中seq 1 10 , 即列出现1到10之间所有的数字,这一行也可改为:for a in "1 2 3 4 5 6 7 8 9 10" 2. 写一个脚本,执行后,打印一行提示“Please input a number:",要求用户输入数值,然 后打印出该数值,然后再次要求用户输入数值。直到用户输入 "end"停止。 #!/bin/sh

while [ "$var" != "end" ] do echo -n "please input a number: " read var if [ "$var" = "end" ] then break fi echo "var is $var" done 3. 写一个脚本,利用循环和continue关键字,计算100以内能被3整除的数之和#!/bin/sh sum=0 for a in `seq 1 100` do if [ `expr $a % 3` -ne 0 ] then continue

echo $a sum=`expr $sum + $a` done echo "sum = $sum" 4.一个函数,利用shift计算所有参数乘积,假设参数均为整数( 特殊变量$# 表示包含参数的个数) #! /bin/sh result=1 while [ $# -gt 0 ] do result=`expr $result \* $1` shift done echo $result 5.写一个脚本,可以根据参数文件名,以正确的参数调用tar来解压缩tar.gz或tar.bz2文件。 #!/bin/sh

PowerShell基础教程

PowerShell基础教程一:Windows PowerShell简介 XP/Server 2003/Vista/Server 2008操作系统的脚本语言。包括 Cmd.exe 、SH、KSH、CSH以及BASH Unix在内的大多数外壳程序的操作方式都是在新的进程中执行命令或实用工具程序,并以文本格式向用户显示结果。多年以来,许多文本处理实用工具程序,如sed、AWK 和 PERL,都已逐渐发展为支持这种交互模式。 这些外壳程序也会提供内置于外壳程序中并在外壳程序处理器中执行的 命令,例如KSH 中的typeset命令和以及 Cmd.exe 中的 dir 命令。在大多数外壳程序中,由于内置命令数量少,从而导致许多实用工具程序应运而生。 针对这一点,Windows PowerShell 有不同的做法。 ◆ Windows PowerShell 并不处理文本,而是处理以.NET平台为基础的对象; ◆Windows PowerShell 附带了数量庞大的内置命令集和一致的接口; ◆对于各个工具,全部的外壳程序命令都使用相同的命令剖析器,而非使用不同的剖析器,这项特点会使你更容易学会每种命令的使用方式。 其中最棒的就是你完全不需要舍弃已使用习惯的工具,你可以继续在Windows PowerShell 中使用诸如Net、SC 和 Reg.exe 等传统的 Windows 工具。 Windows PowerShell Cmdlet Cmdlet (发音如“command-let”) 是指在 Windows PowerShell 中用来操作对象的单一功能命令。你可以依据其名称格式来加以辨识 Cmdlet -- 以破折号 (-) 分隔的动词和名词,例如Get-Help、Get-Process 和 Start-Service。 在传统的外壳程序中,命令是极为简单 (例如 attrib.exe) 到极为复杂 (例如 netsh.exe) 范围内的可执行程序。 在 Windows PowerShell 中,大多数Cmdlet 都相当简单,而且设计成与其他Cmdlet 结合使用。例如,"get" Cmdlet 只提取数据,"set" Cmdlet 只创建或修改数据,"format" Cmdlet 只格式化数据,而 "out" Cmdlet 只将输出导向到指定的目的地。每种 Cmdlet 都具备可在输入下列命令时加以显示的说明文件:

Linux操作系统下shell的工作原理

Linux下shell的工作原理 Bourne shell 允许您执行文件名替换。 命令参数经常是文件名。可以自动产生文件名的列表,作为命令行上的参数。要这样做,请指定shell 识别为模式匹配字符的字符。当命令包含这样的字符时,shell 使用目录中的文件名替换它。 注:Bourne shell 不支持基于等价字符分类的文件名扩展。 Bourne Shell 最初的UNIX shell是由Stephen R. Bourne于20世纪70年代中期在新泽西的AT&T贝尔实验室编写的,这就是Bourne shell。Bourne shell 是一个交换式的命令解释器和命令编程语言。Bourne shell 可以运行为login shell或者login shell的子shell(subshell)。只有login命令可以调用Bourne shell作为一个login shell。此时,shell先读取/etc/profile文件和$HOME/.profile文件。/etc/profile文件为所有的用户定制环境,$HOME/.profile文件为本用户定制环境。最后,shell会等待读取你的输入。 C Shell Bill Joy于20世纪80年代早期,在Berkeley的加利福尼亚大学开发了C shell。它主要是为了让用户更容易的使用交互式功能,并把ALGOL风格的语法结构变成了C语言风格。它新增了命令历史、别名、文件名替换、作业控制等功能。 Korn Shell 有很长一段时间,只有两类shell供人们选择,Bourne shell用来编程,C shell用来交互。为了改变这种状况,AT&T的bell实验室David Korn开发了Korn shell。ksh结合了所有的C shell的交互式特性,并融入了Bourne shell的语法。因此,Korn shell广受用户的欢迎。它还新增了数学计算,进程协作(coprocess)、行内编辑(inline editing)等功能。Korn Shell 是一个交互式的命令解释器和命令编程语言.它符合POSIX——一个操作系统的国际标准.POSIX不是一个操作系统,而是一个目标在于应用程序的移植性的标准——在源程序一级跨越多种平台。 Bourne Again Shell (bash) bash是GNU计划的一部分,用来替代Bourne shell。它用于基于GNU的系统如Linux.大多数的Linux(Red Hat, Slackware, Caldera)都以bash作为缺省的shell,并且运行sh时,其实调用的是bash。 POSIX Shell POSIX shell 是Korn shell的一个变种. 当前提供POSIX shell的最大卖主是Hewlett-Packard。在HP-UX 11.0 , POSIX shell 就是/bin/sh,而bsh是/usr/old/bin/sh.

很实用的Shell脚本(实践版)

ApacheLogRotate.sh echo`date`":Clean the apache logs" >/usr/WebSphere/IHS/logs/access_log >/usr/WebSphere/IHS/logs/error_log apforwinbk.sh export DayOfWeek=`date+"%u"` cd/wasbackup cp-rf./WASBackup_"$DayOfWeek".tar./apbk archiveOld.sh export TargetDir=/erpHome/jln.ear/erp.war/$1/$2 export TT=`date+"%Y%m%d"` export DayOfWeek=`date+"%u"` if(test-e$TargetDir)then mkdir-p/erpHome/shell/old/$1 cd$TargetDir #zip-qm/erpHome/old/$1/$2_$TT.zip`find.-mtime+7|awk'{print$0}'` mv/erpHome/shell/old/$1/$2_$DayOfWeek.zip/erpHome/shell/old/$1/$2.zip.old find.-mtime+7|xargs nice-n20zip-qm /erpHome/shell/old/$1/$2_$DayOfWeek.zip #find.-mtime+7 Fi

archiveOld2.sh ./erpHome/shell/setP.sh export DayOfWeek=`date+"%u"` if test"$#"-lt1||test-z"$1" then echo At least one argument needed. exit fi if test!-e"$ShellHome/old/$1" then cd$ShellHome/old/ mkdir-p$1 fi if test!-e"$ERPHome/$1" then echo"$ERPHome/$1""does not exist" exit fi cd$ERPHome/$1 mv$ShellHome/old/$1_$DayOfWeek.zip$ShellHome/old/$1.zip.old find.-mtime+7-type f|xargs nice-n20zip-qm$ShellHome/old/$1_$DayOfWeek.zip #find.-mtime+7-type f

Linux目前流行Shell一览

Linux目前流行Shell一览(图) 本刊2005年4月期刊登的《Linux Shell编程入门》一文,介绍了在Linux中进行Shell教本编程的部分知识。由于篇幅所限没有介绍太多介绍目前主要Shell的种类,在此进行补充。 目前流行的Shell有bash、ksh、csh,用一个图表表示它们的关系如图。 bash bash是Linux系统默认使用的Shell,它由Brian Fox和Chet Ramey共同完成,是Bourne Again Shell的缩写,内部命令一共有40个。Linux使用它作为默认的Shell是因为它有以下的特色:(1)可以使用类似DOS下面的doskey的功能,用上下方向键查阅和快速输入并修改命令。 (2)自动通过查找匹配的方式,给出以某字串开头的命令。 (3)包含了自身的帮助功能,你只要在提示符下面键入help就可以得到相关的帮助。 ksh ksh是Korn Shell的缩写,由Eric Gisin编写,共有42条内部命令。该Shell最大的优点是几乎和商业发行版的ksh完全相容,这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。 csh csh是Linux比较大的内核,它由以William Joy为代表的共计47位作者编成,共有52个内部命令。该Shell其实是指向/bin/tcsh这样的一个Shell,也就是说,csh其实就是tcsh。 shell编程之 shell问答录 前些天在CU上讨论一个统计正在执行的脚本数量的问题过程中,发现自己对于shell如何执行命令方面了解还是甚少,惭愧惭愧...期间得到waker兄的指点,在此表示感谢!他的说法除了个别地方不太准确外,基本上是正确的。这些天抽时间找了些资料研究了一下,又

从Linux程序中执行shell(程序、脚本)并获得输出结果

Contents 1. 前言 2. 使用临时文件 3. 使用匿名管道 4. 使用popen 5. 小结 1. 前言 Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作。比如实现一个ping程序来测试网络的连通性,实现ping函数需要写上200~300行代码,为什么不能直接调用系统的ping命令呢?通常在程序中通过system函数来调用shell命令。但是,system函数仅返回命令是否执行成功,而我们可能需要获得shell命令在控制台上输出的结果。例如,执行外部命令ping后,如果执行失败,我们希望得到ping的返回信息。 2. 使用临时文件 首先想到的方法就是将命令输出重定向到一个临时文件,在我们的应用程序中读取这个临时文件,获得外部命令执行结果,代码如下所示: #define CMD_STR_LEN 1024 int mysystem(char* cmdstring, char* tmpfile) { char cmd_string[CMD_STR_LEN]; tmpnam(tmpfile); sprintf(cmd_string, "%s > %s", cmdstring, tmpfile); return system(cmd_string); } 这种使用使用了临时文件作为应用程序和外部命令之间的联系桥梁,在应用程序中需要读取文件,然后再删除该临时文件,比较繁琐,优点是实现简单,容易理解。有没有不借助临时文件的方法呢? 3. 使用匿名管道 在<>一书中给出了一种通过匿名管道方式将程序结果输出到分页程序的例子,因此想到,我们也可以通过管道来将外部命令的结果同应用程序连接起来。方法就是fork一个子进程,并创建一个匿名管道,在子进程中执行shell命令,并将其标准输出dup 到匿名管道的输入端,父进程从管道中读取,即可获得shell 命令的输出,代码如下: int mysystem(char* cmdstring, char* buf, int len) { int fd[2]; pid_t pid;

LinuxBashShell入门教程

BASH 的基本语法 ?最简单的例子—— Hello World! ?关于输入、输出和错误输出 ?BASH 中对变量的规定(与C 语言的异同) ?BASH 中的基本流程控制语法 ?函数的使用 2.1 最简单的例子—— Hello World! 几乎所有的讲解编程的书给读者的第一个例子都是Hello World 程序,那么我们今天也就 从这个例子出发,来逐步了解BASH。 用vi 编辑器编辑一个hello 文件如下:#!/bin/bash # This is a very simple exampleecho Hello World 这样最简单的一个BASH 程序就编写完了。这里有几个问题需要说明一下: 一,第一行的#! 是什么意思二,第一行的/bin/bash 又是什么意思三,第二行是注释吗四,echo 语句五,如何执行该程序 #! 是说明hello 这个文件的类型的,有点类似于Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不相同)。Linux 系统根据"#!" 及该字串后面的信息确定该文件的类型,关于这一问题同学们回去以后可以通过"man magic"命令及/usr/share/magic 文件来了解这方面的更多内容。在BASH 中第一行的"#!" 及后面的"/bin/bash" 就表明该 文件是一个BASH 程序,需要由/bin 目录下的bash 程序来解释执行。BASH 这个程序 一般是存放在/bin 目录下,如果你的Linux 系统比较特别,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或/usr/local/sbin 这样的目录下;如果还找不到,你可以用"locate bash" "find / -name bash 2> /dev/null" 或"whereis bash" 这三 个命令找出bash 所在的位置;如果仍然找不到,那你可能需要自己动手安装一个BASH 软件包了。 第二行的"# This is a ..." 就是BASH 程序的注释,在BASH 程序中从“#”号(注意:后 面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释。的三行的echo 语句的功能是把echo 后面的字符串输出到标准输出中去。由于echo 后跟的是"Hello World" 这个字符串,因此"Hello World"这个字串就被显示在控制台终端的屏幕上了。需要注意的是BASH 中的绝大多数语句结尾处都没有分号。 如何执行该程序呢?有两种方法:一种是显式制定BASH 去执行: $ bash hello 或$ sh hello (这里sh 是指向bash 的一个链接,“lrwxrwxrwx 1 root root 4 Aug 20 05:41 /bin/sh -> bash”) 或者可以先将hello 文件改为可以执行的文件,然后直接运行它,此时由于hello 文件第 一行的"#! /bin/bash" 的作用,系统会自动用/bin/bash 程序去解释执行hello 文件的:$ chmod u+x hello$ ./hello 此处没有直接“$ hello”是因为当前目录不是当前用户可执行文件的默认目录,而将当前目 录“.”设为默认目录是一个不安全的设置。

(完整版)Linux下Shell编程

Linux下Shell编程 本文内容 ?Shell命令行的运行 ?编写、修改权限和执行shell程序的步骤 ?在shell程序中使用参数和变量 ?表达式比较、循环结构语句和条件结构语句 ?在shell程序中使用函数和调用其他shell程序 一、Shell命令行书写规则 学习目标 Shell命令行的书写规则 对shell命令行基本功能的理解有助于编写更好的shell程序,在执行shell命令时多个命令可以在一个命令行上运行,但此时要使用分号(:)分隔命令,例如: [root@localhost root]# ls a* -l;free;df 长shell命令行可以使用反斜线字符(\)在命令行上扩充,例如: [root@localhost root]#echo “this is \ >long command” This is long command 注意: “>”符号是自动产生的,而不是输入的。 二、编写/修改权限及执行shell程序的步骤 学习目标 编写shell程序 执行shell程序 Shell程序有很多类似C语言和其他程序设计语言的特征,但是又没有程序语言那样的复杂。Shell程序是指放在一个文件中的一系列Linux命令和实用程序。在执行的时候,通过Linux操作系统一个接一个地解释和执行每条命令。首先,来编写第一个shell程序,从中学习shell程序的编写、修改权限、执行过程。 (一)编辑shell程序 编辑一个内容如下的源程序,保存文件名为date,可将其存放在目录/bin下。 [root@localhost bin]#vi date #!/bin/sh echo “Mr.$USER,Today is:” echo &date “+%B%d%A” echo “Wish you a lucky day!”

Linux常用shell命令大全

第2讲 Linux常用shell命令 使用LINUX虚拟机的快照3 以下文章由影视网收集于提供https://www.doczj.com/doc/fe7644068.html, 实验目的: 掌握Linux常用命令 实验步骤: 一、基本命令 1、立即关机并重启动,执行如下命令: shutdown -r now 或者reboot 2、立即关机,执行如下命令: shutdown -h now 或者poweroff 3、等待2分钟关机并重启动,执行如下命令: shutdown -r 2 4、等待2分钟关机,执行如下命令: shutdown -h 2 5、使用当前用户的历史命令,执行如下操作: history 将会显示使用过的每条命令及其序号,可利用序号重复执行该命令。 例如输入!1并回车,将会重复执行第1条历史命令。 也可用上下光标键调出某条历史命令,然后按回车键重复执行。还可用上下光标键调出某条历史命令,修改后按回车键执行。 6、清除当前用户的历史命令,执行如下命令: history -c 此时用向上光标键将会调不出任何历史命令。 7、命令提示键:输入命令开头一个或几个字母,然后按1次【Tab】键,系统会自动补全能够识别的部分;再按1次【Tab】键,系统显示出符合条件的所有命令供用户选择。 例如输入group后按两次键,将会显示以group开头的所有命令。 8、显示内核版本号,执行如下命令: uname -r 注:内核版本号不同于软件发行版本号。例如,RHEL 5.4的内核版本号是2.6.18-164.el5,软件发行版本号是5.4。 9、清除屏幕,执行如下命令: clear 10、显示操作系统时钟,执行如下命令: date 11、加载光盘到/media,执行如下命令: mount /dev/cdrom /media 12、卸载光盘,执行如下命令: umount /dev/cdrom 或者 umount /media 注意:不要在/media或其子目录中执行此命令,否则将会出现“设备忙错误”。 13、查看存储设备,执行如下命令: fdisk –l 14、加载U盘到/media

Linux Shell概述

Linux Shell概述 英文shell的本意是“壳”。它形象地说明了shell在Linux系统中的作用。shell 就是紧紧包裹在Linux内核外面的一个壳程序。用户让操作系统做的所有任务,都是通过shell与系统内核的交互来完成的。shell所处的地位,就相当于DOS中的https://www.doczj.com/doc/fe7644068.html,程序,但比https://www.doczj.com/doc/fe7644068.html,的功能更加强大。 shell是用户与操作系统的内核之间的接口,是系统的用户界面,并且具有相当丰富的功能。利用shell可以编写出代码简捷,但功能很强的脚本文件。 1 了解Shell Shell是使用Linux系统的基本环境。虽然不使用Shell,通过X Window也能操作Linux,但是,无论如何看待文本环境下的工作,都可以肯定地说,一旦全面体验到纯文本的强大功能,就会被它所折服。文本就是简洁,文本就是速度。管理网络的系统管理员在使用Shell方面是最有经验的。那些被迫在慢速调制解调器连接上使用图形工具的用户很快也会被折服。 Shell提供了用户与操作系统之间通信的方式,可以以交互方式(从键盘输入,并且可以立即得到响应)执行,也可以以非交互方式(shell script方式)执行。这里的shell script是放在文件中的一串shell和操作系统命令,它们可以重复使用,本质上,shell script是将命令行命令简单地组合到一个文件里面。 此外,shell还可分为交互式shell和非交互式shell。其中,交互式模式是指shell 等待用户的输入,并且执行用户提交的命令,由于需要与用户进行交互,因而被称为交互式shell;这种模式也是大多数用户所熟悉的:登录、执行一些命令、退出,当用户退出系统后,shell也就终止了。shell也可以在非交互式模式下运行,在这种模式下,shell不与用户进行交互,而是读取存放在文件中的命令,并且执行它们,当读到文件尾时,shell将终止。 shell是用户和Linux内核之间的接口程序,如果把Linux内核想象成一个球体的中心,那么shell就是围绕内核的外层。当从shell或者其他程序向Linux传送命令时,内核就会作出相应的反应。shell作为一个命令语言解释程序,拥有内建的shell 命令集;shell也能被系统中其他应用程序调用。用户在提示符后输入的命令都是先由shell解释,然后再传给Linux内核的。 1.2 shell的特点 Linux 系统为用户提供了shell 高级程序设计语言,大大方便了管理人员对系

相关主题
文本预览
相关文档 最新文档