shell编程 请问shell编程是什么请高手指点!
亲爱的读者们,你是否对shell编程和请问shell编程是什么请高手指点!的相关问题感到困惑?别担心,今天我将为你解答这些问题,让你对此有更清晰的认识。
简单的shell编程
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<fcntl.h>
#define BUFFERSIZE 80
extern char*get_current_dir_name(void);
extern char*getenv(const char*name);
extern pid_t waitpid(pid_t pid, int*status, int options);
char buffer[BUFFERSIZE+1];
main()
{
char*path,*arg[10],*input;
int li_inputlen, is_bj, is_back, i, j, k, pid, status;
char lc_char;
while(1){
/* initiations*/
is_bj= 0;/*redirection flag*/
is_back= 0;/*background*/
/* shell prompt*/
path= get_current_dir_name();
printf("%s>$",path);
/*开始获取输入*/
li_inputlen= 0;
lc_char= getchar();
while(lc_char!='\n'){
if(li_inputlen< BUFFERSIZE)
buffer[li_inputlen++]= lc_char;
lc_char= getchar();
}
/*命令超长处理*/
if(li_inputlen>= BUFFERSIZE){
printf("Your command is too long! Please re-enter your command!\n");
li_inputlen= 0;/*reset*/
continue;
}
else
buffer[li_inputlen]='\0';/*加上串结束符号,形成字串*/
/*将命令从缓存拷贝到input中*/
input=(char*) malloc(sizeof(char)*(li_inputlen+1));
strcpy(input,buffer);
/*获取命令和参数并保存在arg中*/
for(i= 0,j= 0,k= 0;i<= li_inputlen;i++){
/*管道和重定向单独处理*/
if(input[i]=='<'|| input[i]=='>'|| input[i]=='|'){
if(input[i]=='|')
pipel(input,li_inputlen);
else
redirect(input,li_inputlen);
is_bj= 1;
break;
}
/*处理空格、TAB和结束符。不用处理‘\n',大家如果仔细分析前面的获取输入的程序的话,
*不难发现回车符并没有写入buffer*/
if(input[i]==''|| input[i]=='\t'|| input[i]=='\0'){
if(j== 0)/*这个条件可以略去连在一起的多个空格或者tab*/
continue;
else{
buffer[j++]='\0';
arg[k]=(char*) malloc(sizeof(char)*j);
/*将指令或参数从缓存拷贝到arg中*/
strcpy(arg[k],buffer);
j= 0;/*准备取下一个参数*/
k++;
}
}
else{
/*如果字串最后是‘&',则置后台运行标记为1*/
if(input[i]=='&'&& input[i+1]=='\0'){
is_back= 1;
continue;
}
buffer[j++]= input[i];
}
}
free(input);/*释放空间*/
/*如果输入的指令是leave则退出while,即退出程序*/
if(strcmp(arg[0],"leave")== 0){
printf("bye-bye\n");
break;
}
/*如果输入的指令是about则显示作者信息,同时结束本条命令的解析过程*/
if(strcmp(arg[0]," about")== 0){
printf("copyright by shike,shike13@163.com\n");
continue;
}
if(is_bj== 0){/*非管道、重定向指令*/
/*在使用xxec执行命令的时候,最后的参数必须是NULL指针,
*所以将最后一个参数置成空值*/
arg[k]=(char*) 0;
/*判断指令arg[0]是否存在*/
if(is_fileexist(arg[0])==-1){
printf("This command is not found?!\n");
for(i=0;i<k;i++)
free(arg[i]);
continue;
}
/* fork a sub-process to run the execution file*/
if((pid= fork())==0)/*子进程*/
execv(buffer,arg);
else/*父进程*/
if(is_back== 0)/*并非后台执行指令*/
waitpid(pid,&status,0);
/*释放申请的空间*/
for(i=0;i<k;i++)
free(arg[i]);
}
}
}
int is_fileexist(char*comm)
{
char*path,*p;
int i;
i= 0;
/*使用getenv函数来获取系统环境变量,用参数PATH表示获取路径*/
path= getenv("PATH");
p= path;
while(*p!='\0'){
/*路径列表使用‘:’来分隔路径*/
if(*p!=':')
buffer[i++]=*p;
else{
buffer[i++]='/';
buffer[i]='\0';
/*将指令和路径合成,形成pathname,并使用access函数来判断该文件是否存在*/
strcat(buffer,comm);
if(access(buffer,F_OK)== 0)/*文件被找到*/
return 0;
else
/*继续寻找其它路径*/
i= 0;
}
p++;
}
/*搜索完所有路径,依然没有找到则返回-1*/
return-1;
}
int redirect(char*in,int len)
{
char*argv[30],*filename[2];
pid_t pid;
int i,j,k,fd_in,fd_out,is_in=-1,is_out=-1,num= 0;
int is_back= 0,status=0;
/*这里是重定向的命令解析过程,其中filename用于存放重定向文件,
*is_in, is_out分别是输入重定向标记和输出重定向标记*/
for(i= 0,j= 0,k= 0;i<= len;i++){
if(in[i]==''||in[i]=='\t'||in[i]=='\0'||in[i]=='<'||in[i]=='>'){
if(in[i]=='>'|| in[i]=='<'){
/*重定向指令最多'<','>'各出现一次,因此num最大为2,
*否则认为命令输入错误*/
if(num< 3){
num++;
if(in[i]=='<')
is_in= num- 1;
else
is_out= num- 1;
/*处理命令和重定向符号相连的情况,比如ls>a*/
if(j> 0&& num== 1){
buffer[j++]='\0';
argv[k]=(char*) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
j= 0;
}
}
else{
printf("The format is error!\n");
return-1;
}
}
if(j== 0)
continue;
else{
buffer[j++]='\0';
/*尚未遇到重定向符号,字符串是命令或参数*/
if(num== 0){
argv[k]=(char*) malloc(sizeof(char)*j);
strcpy(argv[k],buffer);
k++;
}
/*是重定向后符号的字符串,是文件名*/
else{
filename[status]=(char*) malloc(sizeof(char)*j);
strcpy(filename[status++],buffer);
}
j= 0;/*initate*/
}
}
else{
if(in[i]=='&'&& in[i+1]=='\0'){
is_back= 1;
continue;
}
buffer[j++]= in[i];
}
}
argv[k]=(char*) 0;
if(is_fileexist(argv[0])==-1){
printf("This command is not founded!\n");
for(i=0;i<k;i++)
free(argv[i]);
return 0;
}
if((pid= fork())==0){
/*存在输出重定向*/
if(is_out!=-1)
if((fd_out=open(filename[is_out],O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR))==-1){
printf("Open out%s Error\n",filename[is_out]);
return-1;
}
/*存在输入重定向*/
if(is_in!=-1)
if((fd_in=open(filename[is_in],O_RDONLY,S_IRUSR|S_IWUSR))==-1){
printf("Open in%s Error\n",filename[is_out]);
return-1;
}
if(is_out!=-1)
/*使用dup2函数将标准输出重定向到fd_out上,dup2(int oldfd,int newfd)实现的
*是把oldfd所指的文件描述符复制到newfd。若newfd为一已打开的文件描述词,
*则newfd所指的文件会先被关闭,dup2复制的文件描述词与原来的文件描述词
*共享各种文件状态*/
if(dup2(fd_out,STDOUT_FILENO)==-1){
printf("Redirect Standard Out Error\n");
exit(1);
}
if(is_in!=-1)
if(dup2(fd_in,STDIN_FILENO)==-1){
printf("Redirect Standard Out Error\n");
exit(1);
}
execv(buffer,argv);
}
else
if(is_back== 0)/*run on the TOP*/
waitpid(pid,&status,0);
for(i=0;i<k;i++)
free(argv[i]);
if(is_in!=-1){
free(filename[is_in]);
close(fd_in);
}
if(is_out!=-1){
free(filename[is_out]);
close(fd_out);
}
return 0;
}
int pipel(char*input,int len)
{
char*argv[2][30];
int i,j,k,count,is_back= 0;
int li_comm= 0,fd[2],fpip[2];
char lc_char,lc_end[1];
pid_t child1,child2;
/*管道的命令解析过程*/
for(i= 0,j= 0,k= 0;i<= len;i++){
if(input[i]==''|| input[i]=='\t'|| input[i]=='\0'|| input[i]=='|'){
if(input[i]=='|')/*管道符号*/
{
if(j> 0)
{
buffer[j++]='\0';
/*因为管道连接的是两个指令,所以用二维数组指针来存放命令和参数,
*li_comm是表示第几个指令*/
argv[li_comm][k]=(char*) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k++],buffer);
}
argv[li_comm][k++]=(char*) 0;
/*遇到管道符,第一个指令完毕,开始准备接受第二个指令*/
li_comm++;
count= k;
k=0;j=0;
}
if(j== 0)
continue;
else
{
buffer[j++]='\0';
argv[li_comm][k]=(char*) malloc(sizeof(char)*j);
strcpy(argv[li_comm][k],buffer);
k++;
}
j= 0;/*initate*/
}
else{
if(input[i]=='&'&& input[i+1]=='\0'){
is_back= 1;
continue;
}
buffer[j++]= input[i];
}
}
argv[li_comm][k++]=(char*) 0;
if(is_fileexist(argv[0][0])==-1){
printf("This first command is not found!\n");
for(i=0;i<count;i++)
free(argv[0][i]);
return 0;
}
/*指令解析结束*/
/*建立管道*/
if(pipe(fd)==-1){
printf("open pipe error!\n");
return-1;
}
/*创建第一个子进程执行管道符前的指令,并将输出写到管道*/
if((child1= fork())==0){
/*关闭读端*/
close(fd[0]);
if(fd[1]!= STDOUT_FILENO){
/*将标准输出重定向到管道的写入端,这样该子进程的输出就写入了管道*/
if(dup2(fd[1],STDOUT_FILENO)==-1){
printf("Redirect Standard Out Error\n");
return-1;
}
/*关闭写入端*/
close(fd[1]);
}
execv(buffer,argv[0]);
}
else{/*父进程*/
/*先要等待写入管道的进程结束*/
waitpid(child1,&li_comm,0);
/*然后我们必须写入一个结束标记,告诉读管道进程数据到这里就完了*/
lc_end[0]= 0x1a;
write(fd[1],lc_end,1);
close(fd[1]);
if(is_fileexist(argv[1][0])==-1){
printf("This command is not founded!\n");
for(i=0;i<k;i++)
free(argv[1][i]);
return 0;
}
/*创建第二个进程执行管道符后的指令,并从管道读输入流*/
if((child2= fork())== 0){
if(fd[0]!= STDIN_FILENO){
/*将标准输入重定向到管道读入端*/
if(dup2(fd[0],STDIN_FILENO)==-1){
printf("Redirect Standard In Error!\n");
return-1;
}
close(fd[0]);
}
execv(buffer,argv[1]);
}
else/*父进程*/
if(is_back== 0)
waitpid(child2,NULL,0);
}
for(i=0;i<count;i++)
free(argv[0][i]);
for(i=0;i<k;i++)
free(argv[1][i]);
return 0;
}
以前写的,好像一些细节不一样,不明白的地方,发邮件给我,shike13@163.com
请问shell编程是什么请高手指点!
shell是一个命令处理器(command processor)——是一个读入并解释你输入的命令的程序。除了是一个命令中断器以外,shell还是一个程序设计语言。你可以编写shell可以解释的程序(被称为源程序),这些源程序可以包含shell程序设计命令等等。shell除了解释命令以外,还有其他工作,它也可以配置和编程。shell拥有自己的语言允许用户编写程序并以一种复杂方式运行。shell编程语言具有许多常用的编程语言的特征,例如:循环和控制结构等。用户可以生成像其他应用程序一样复杂的shell程序。
补充说明:简单的说: shell是一个交互性命令解释器。shell独立于操作系统,这种设计让用户可以灵活选择适合自己的shell。shell让你在命令行键入命令,经过shell解释后传送给操作系统(内核)执行。
一下是shell功能的一个汇总:
查找命令的位置并且执行相关联的程序。
为shell变量赋新值
执行命令替代
处理 I/O重定向和管道功能
提供一个解释性的编程语言界面,包括tests、branches和loops等语句
VB中的shell函数是干什么的怎么用啊
Shell函数是VB中的内部函数,它负责执行一个可执行文件,返回一个Variant(Double),如果成功的话,代表这个程序的进程ID,若不成功,则会返回0,shell一个非常重要的特性是它可作为一种编程语言来使用。
Shell的语法:Shell(PathName[,WindowStyle])。
PathName为必需参数,类型为String,它指出了要执行的程序名,以及任何需要的参数或命令行变量。
扩展资料:
因为shell是一个解释器,所以它不能对为它编写的程序进行编译,而是在每次从磁盘加载这些程序时对它们进行解释,而程序的加载和解释都是非常耗时的。
针对此问题,许多shell(如BourneAgainShell)都包含shell函数,shell把这些函数放在内存中,这样每次需要执行它们时就不必再从磁盘读入。
参考资料来源:百度百科-shell函数
什么是shell编程啊,求简单实例
刚刚学习了新书<<实用Linux Shell编程>>,书写的容易懂,第一章就回答了什么是shell编程的问题。下面简单回答,仅供参考,谢谢!
1)linux命令,你可以一条一条执行,例如,显示日期时间命令是date,显示当前目录的命令是pwd,打印一句话的命令可以是echo"good morning"
2)一个脚本是包含多条命令的文本文件,命令将按照顺序依次运行。例如z.sh包含4行,如下:
$ cat z.sh
#!/bin/bash
date
pwd
echo"good morning"
第一行为脚本解释程序的位置/bin/bash,其他行,是命令的“堆放”
3)增加脚本执行权限:
$ chmod+x z.sh
4)运行脚本:
$ z.sh(或者./z.sh)
Mon Jan 12 15:20:32 CST 2015
/home/user
good morning
输出有3行,分别是命令date的结果,命令pwd的结果,命令echo"good morning"的运行结果。
5)一般地,脚本不单单是几个简单命令的“堆放”,有判断、分支选择命令,循环命令,参数输入,函数定义等等。
但是最简单的shell脚本可以就一条命令,或者就几个简单命令的“堆放”。
仅供参考,谢谢!
END,本文到此结束,如果可以帮助到大家,还望关注本站哦!