从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; int n, count;
memset(buf, 0, len);
if (pipe(fd) < 0)
return -1;
if ((pid = fork()) < 0)
return -1;
else if (pid > 0)
{
close(fd[1]);
count = 0;
while ((n = read(fd[0], buf + count, len)) > 0 && count > len)
count += n;
close(fd[0]);
if (waitpid(pid, NULL, 0) > 0)
return -1;
}
else
{
close(fd[0]);
if (fd[1] != STDOUT_FILENO)
{
if (dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
{
return -1;
}
close(fd[1]);
}
if (execl("/bin/sh", "sh", "-c", cmdstring, (char*)0) == -1)
return -1;
}
return 0;
}
4. 使用popen
在学习unix编程的过程中,发现系统还提供了一个popen函数,可以非常简单的处理调用shell,其函数原型如下:
FILE *popen(const char *command, const char *type);
该函数的作用是创建一个管道,fork一个进程,然后执行shell,而shell的输出可以采用读取文件的方式获得。采用这种方法,既避免了创建临时文件,又不受输出字符数的限制,推荐使用。 popen使用FIFO管道执行外部程序。
#include
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
popen 通过type是r还是w确定command的输入/输出方向,r和w是相对command的管道而言的。r表示command从管道中读入,w表示 command通过管道输出到它的stdout,popen返回FIFO管道的文件流指针。pclose则用于使用结束后关闭这个指针。
下面看一个例子:
#include
#include
#include
#include
#include
int main( void )
{
FILE *stream;
FILE *wstream;
char buf[1024];
memset( buf, '/0', sizeof(buf) );//初始化buf,以免后面写如乱码到文件中
stream = popen( "ls -l", "r" ); //将“ls -l”命令的输出 通过管道读取(“r”参数)到FILE* stream
wstream = fopen( "test_popen.txt", "w+"); //新建一个可写的文件
fread( buf, sizeof(char), sizeof(buf), stream); //将刚刚FILE* stream的数据流读取到buf中
fwrite( buf, 1, sizeof(buf), wstream );//将buf中的数据写到FILE *wstream对应的流中,也是写到文件中
pclose( stream );
fclose( wstream );
return 0;
}
[root@localhost src]# gcc popen.c
[root@localhost src]# ./a.out
[root@localhost src]# cat test_popen.txt
总计 128
-rwxr-xr-x 1 root root 5558 09-30 11:51 a.out
-rwxr-xr-x 1 root root 542 09-30 00:00 child_fork.c
-rwxr-xr-x 1 root root 480 09-30 00:13 execve.c
-rwxr-xr-x 1 root root 1811 09-29 21:33 fork.c
-rwxr-xr-x 1 root root 162 09-29 18:54 getpid.c
-rwxr-xr-x 1 root root 1105 09-30 11:49 popen.c
-rwxr-xr-x 1 root root 443 09-30 00:55 system.c
-rwxr-xr-x 1 root root 0 09-30 11:51 test_popen.txt
-rwxr-xr-x 1 root root 4094 09-30 11:39 test.txt
5. 小结 有统计数据表明,代码的缺陷率是一定的,与所使用的语言无关。Linux提供了很多的实用工具和脚本,在程序中调用工具和脚本,无疑可以简化程序,从而降低代码的缺陷数目。Linux shell脚本也是一个强大的工具,我们可以根据需要编制脚本,然后在程序中调用自定义脚本。
常用shell脚本指令
常用shell脚本命令
1、显示包含文字aaa的下一行的内容:
sed -n '/aaa/{n;p;}' filename
2、删除当前行与下一行的内容:
sed -i '/aaa/{N;d;}' filename
3、 删除当前行与下两行的内容:
sed -i '/aaa/{N;N;d;}' filename
依次类推,删除三行,则为{N;N;N;d;},分析知:N为next
4、得出以空格为分割的字符串中单词的个数,即统计个数:
awk ' { print NF } '
如显示字符串VALUE中的单词个数,其中VALUE为:aaa bbb ccc ddd ee f
则执行 echo $VALUE | awk ' { print NF } ' 后的结果为6
5、在linux中建立一个文件与另一文件的链接, 即符号链接
ln -s /var/named/chroot/etc/named.conf named.conf
这要就建立了当前目录的文件named.conf对/var/named/chroot/etc/named.conf 的符号链接。即操作named.conf就意味着操作实际文件/var/named/chroot/etc/named.conf ,这时用ll命令查看的结果如:
lrwxrwxrwx 1 root root 32 Mar 22 12:29 named.conf ->
/var/named/chroot/etc/named.conf
注意:当用sed来通过named.conf来删除一部分信息时,会将符号链接的关系丢掉,即会将named.conf变成一个实际文件。所以 需对实际文件进行删除操作。
6、显示指定字符范围内的内容:
如:显示文件test.txt中字符#test begin与#test end之间所有的字符
shell编程实例
shell编程实例
Shell编程是一种脚本语言,广泛应用于Unix和Linux系统中。通过编写Shell脚本,我们可以实现自动化的任务,并提高工作效率。本文将介绍一些常见的Shell编程实例,帮助读者更好地理解和运用Shell脚本。
1. 实例一:文件备份
在Linux系统中,我们经常需要备份重要文件以防意外丢失。下面是一个简单的Shell脚本示例,用于备份指定目录下的所有文件。
```shell
#!/bin/bash
# 定义备份目录和源目录
backup_dir="/home/backup"
source_dir="/home/data"
# 创建备份目录
mkdir -p $backup_dir
# 备份源目录下的所有文件
cp -r $source_dir/* $backup_dir
# 输出备份完成信息
echo "文件备份完成!" ```
以上脚本将源目录`/home/data`下的所有文件备份到目录`/home/backup`中。备份完成后,脚本会输出"文件备份完成!"的提示信息。
2. 实例二:文件批量重命名
有时候我们需要对大量文件进行批量重命名,比如将一个目录下的所有图片文件的扩展名从`.jpeg`改为`.jpg`。下面是一个实现此功能的Shell脚本示例。
```shell
#!/bin/bash
# 定义源目录
source_dir="/home/photos"
# 进入源目录
cd $source_dir
# 重命名扩展名为.jpg的文件
for file in *.jpeg
do
mv "$file" "${file%.jpeg}.jpg"
done # 输出重命名完成信息
echo "文件重命名完成!"
```
以上脚本将目录`/home/photos`下所有扩展名为`.jpeg`的文件重命名为`.jpg`。脚本执行完成后,会输出"文件重命名完成!"的提示信息。
pipeline中获取shell命令的返回值
pipeline中获取shell命令的返回值
pipeline是一种用于连接多个命令的方式,它将一个命令的输出直接作为另一个命令的输入。在shell环境中,我们经常使用pipeline来实现复杂的任务,其中获取shell命令的返回值是一个常见的需求。
在本文中,我们将一步一步回答如何在pipeline中获取shell命令的返回值,并探讨其应用场景和实例。
什么是pipeline?
Pipeline是一种将多个命令连接在一起执行的方式。通过使用管道符号" "将一个命令的输出传递给另一个命令作为输入,可以实现命令的组合和串联。这种方式允许我们将简单的命令组合成复杂的任务,提高了命令行中的操作效率和灵活性。
在Linux和Unix系统中,命令行界面是最常用的操作方式之一。通过合理使用pipeline,我们可以将多个命令组合在一起,实现更复杂的任务。
pipeline中如何获取shell命令的返回值?
在pipeline中获取shell命令的返回值是一个常见的需求。返回值通常是用来判断命令是否执行成功或者获取命令输出的结果。下面我们将介绍两种在pipeline中获取shell命令返回值的方法。
# 方法一:使用管道后的命令执行返回值
在使用pipeline时,我们可以通过使用"set -o pipefail"命令来获取前一个命令的返回值。具体步骤如下:
1. 添加"set -o pipefail"命令到pipeline的开始。这个命令会让整个pipeline的返回值等于最后一个执行失败的命令的返回值。
2. 使用管道符号将多个命令链接在一起。
3. 在pipeline结束后,使用"?"获取整个pipeline的返回值。
下面是一个示例,使用这种方法获取前一个命令的返回值:
set -o pipefail
command1 command2 command3
pipeline_status=?
linux中sh -c的作用
linux中sh -c的作用
sh -c命令是Linux中的一个常用命令,可以用于执行一段shell脚本或命令。它的作用是在命令行中执行一段指定的脚本或命令,可以方便地实现一些复杂的操作和逻辑。
在Linux系统中,sh -c命令通常用于在命令行中执行一些简单或复杂的Shell脚本。通过这个命令,用户可以直接在命令行中输入一段脚本,并立即执行。这在一些需要快速执行一些命令的场景下非常方便。
使用sh -c命令的语法如下:
```shell
sh -c ''
```
其中,``是要执行的Shell脚本或命令。在执行时,sh -c命令会将整个``参数作为一个整体传递给shell解释器进行解析和执行。
sh -c命令的使用非常灵活,可以结合其他命令和参数实现各种功能。下面将介绍一些常见的使用场景和示例。
1. 执行简单命令
sh -c命令可以直接执行一些简单的命令,比如打印一些信息或执行一些系统命令。例如,要在命令行中打印Hello World,可以使用以下命令:
```shell
sh -c 'echo "Hello World"'
```
2. 执行复杂命令或脚本
sh -c命令还可以执行一些复杂的命令或脚本。例如,要执行一个包含多个命令的脚本,可以使用以下命令:
```shell
sh -c 'command1; command2; command3'
```
其中,command1、command2和command3是要执行的具体命令。
3. 传递参数
sh -c命令还可以接受参数,并将其传递给要执行的脚本或命令。例如,要在命令行中执行一个需要参数的脚本,可以使用以下命令:
```shell
sh -c 'script.sh '
```
其中,script.sh是要执行的脚本,和是要传递给脚本的参数。
4. 执行远程命令
sh -c命令还可以用于执行远程命令。例如,要在远程服务器上执行一个命令,可以使用以下命令:
7shell编程实验
项目7 Shell编程(作业在最后)
任务描述:
一、ls命令多次执行的输出结果都重定向到文件ls.log中保存
二、 编写一个Shell脚本文件list.sh,实现以下功能
1. 显示运行脚本时的当前系统时间
2. 列出/etc目录下以字母p开头并以.conf结尾的配置文件名称
3. 将上述显示结果保存至新建文本文件list.txt中
三、编写一个Shell脚本文件list.sh,实现以下功能,按照/etc/hosts文件中的条目逐一ping所有的机器
任务目标:
掌握如何shell编程的语法
掌握如何运行shell编程的运行
掌握管道与输入输出重定向
任务重点:
编写shell脚本
任务难点:
编写shell脚本
知识准备:
7.1.1 Shell的使用
Shell环境是Linux用户(管理员)与Linux操作系统之间的交互界面,在Shell环境中不仅可以输入执行单个的命令,还可以把需要执行的多个命令保存在文本文件中作为shell脚本执行,使管理任务简单化。
一、Shell的产生和发展
1.Shell的基本概念
Shell是操作系统中运行的程序,与系统中的其他程序不同,Shell程序位于操作系统内核与用户之间,负责接收用户输入的命令,在对已输入放入命令解释,将需要执行的命令程序传递给操作系统内核执行,因此Shell程序充当了一个“命令解释器”。简单shell的定义:是用户和内核之间的接口程序,是命令语言解释器,拥有自己的命令集,它能被系统中其他应用程序调用,在提示符下输入的命令,先由SHELL解释,再交给LINUX内核。 硬件
Kernel
Shelll
用户
用户 输入
输出
硬件 Utility Shell
Kernel 图7.1 Shell的角色
在微软的操作系统中,DOS中的command.exe程序和Windows中的cmd.exe都属于Shell程序。在UNIX操作系统中存在多种类型的Shell程序,下面简单了解Shell的功能。
Linux下使用popen()执行shell命令
Linux下使⽤popen()执⾏shell命令
简单说⼀下popen()函数,可以⽤linux命令来简化⼀些操作,例如grep进程名,判断进程是否存在。
函数定义
#include
FILE * popen(const char *command , const char *type );
int pclose(FILE *stream);
函数说明
popen()函数通过创建⼀个管道,调⽤fork()产⽣⼀个⼦进程,执⾏⼀个shell以运⾏命令来开启⼀个进程。这个管道必须由pclose()函
数关闭,⽽不是fclose()函数。pclose()函数关闭标准I/O流,等待命令执⾏结束,然后返回shell的终⽌状态。如果shell不能被执⾏,则
pclose()返回的终⽌状态与shell已执⾏exit⼀样。
type参数只能是读或者写中的⼀种,得到的返回值(标准I/O流)也具有和type相应的只读或只写类型。如果type是"r"则⽂件指针连接
到command的标准输出;如果type是"w"则⽂件指针连接到command的标准输⼊。
command参数是⼀个指向以NULL结束的shell命令字符串的指针。这⾏命令将被传到bin/sh并使⽤-c标志,shell将执⾏这个命令。
popen()的返回值是个标准I/O流,必须由pclose来终⽌。前⾯提到这个流是单向的(只能⽤于读或写)。向这个流写内容相当于写⼊
该命令的标准输⼊,命令的标准输出和调⽤popen()的进程相同;与之相反的,从流中读数据相当于读取命令的标准输出,命令的标准输⼊
和调⽤popen()的进程相同。
返回值
如果调⽤fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如
果调⽤fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。
shelllinux中如何用shell写一个占用CPU的脚本
shelllinux中如何⽤shell写⼀个占⽤CPU的脚本
使⽤场景:
向公司申请的虚机资源⾃⼰⼯作⽤的⽐较⽅便,因占⽤较⼩basis要求回收掉,现写⼀个脚本,让CPU跑满⼀些。
⾸先看下共有⼏颗逻辑CPUcat /proc/cpuinfo |grep "processor"|wc -l
上图可以看到是4颗,我现在跑满2颗
脚本如下
#! /bin/bash
# filename killcpu.sh
endless_loop()
{
echo -ne "i=0;
while true
do
i=i+100;
i=100
done" | /bin/bash &
}
if [ $# != 1 ] ; then
echo "USAGE: $0 "
exit 1;
fi
for i in `seq $1`
do
endless_loop
pid_array[$i]=$! ;
done
for i in "${pid_array[@]}"; do
echo 'kill ' $i ';';
done
使⽤时后⾯加的参数就是需要跑满的逻辑CPU数量,我这⾥跑2颗
执⾏脚本后,可以看到上图左侧监控到已经跑满了2颗CPU
脚本会⾃动输出2个进程号码,每颗CPU会对应⼀个。
后期也可以在TOP中看⾼占⽤的PID号,⼿动进⾏kill 如下图~
杀掉进程
到此这篇关于shell linux中如何⽤shell写⼀个占⽤CPU的脚本的⽂章就介绍到这了,更多相关shell占⽤CPU脚本内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
LINUX SHELL
LINUX SHELL
linuxshell
Linux shell主要命令的详细说明
shell是用户和linux操作系统之间的接口。linux中有多种shell,其中缺省使用的是bash。本章讲述了shell的工作原理,shell的种类,shell的一般操作及bash的特性。
什么是贝壳
linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言的统称。
Shell是用户和Linux内核之间的接口程序。如果你认为Linux内核是一个球体的中心,那么外壳就是内核的外层。当命令从shell或其他程序传递到Linux时,内核将做出相应的响应。
shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给linux核心。
shell中包含了一些命令,例如更改工作目录命令CD。其他命令,如copy命令CP和move命令RM,是存在于文件系统目录中的独立程序。对于用户来说,命令是构建在shell中还是构建在单独的程序中并不重要。
shell首先检查命令是否是内部命令,若不是再检查是否是一个应用程序(这里的应用程序可以是linux本身的实用程序,如ls和rm,也可以是购买的商业程序,如xv,或者是自由软件,如emacs)。然后shell在搜索路径里寻找这些应用程序(搜索路径就是一个能找到可执行程序的目录列表)。如果键入的命令不是一个内部命令并且在路径里没有找到这个可执行文件,将会显示一条错误信息。如果能够成功找到命令,该内部命令或应用程序将被分解为系统调用并传给linux内核。
shell的另一个重要特性是它是一种解释性编程语言。Shell编程语言支持高级语言中可以看到的大多数程序元素,例如函数、变量、数组和程序控制结构。Shell编程语言简单易学。可以在提示符下键入的任何命令都可以放入可执行的shell程序中。
linux下shell脚本执行方法及exec和source命令
linux下shell脚本执行方法及exec和source命令
exec和source都属于bash内部命令(builtins commands),在bash下输入man exec或man source可以查看所有的内部命令信息。
bash shell的命令分为两类:外部命令和内部命令。外部命令是通过系统调用或独立的程序实现的,如sed、awk等等。内部命令是由特殊的文件格式(.def)所实现,如cd、history、exec等等。
在说明exe和source的区别之前,先说明一下fork的概念。
fork是linux的系统调用,用来创建子进程(child process)。子进程是父进程(parent process)的一个副本,从父进程那里获得一定的资源分配以及继承父进程的环境。子进程与父进程唯一不同的地方在于pid(process id)。
环境变量(传给子进程的变量,遗传性是本地变量和环境变量的根本区别)只能单向从父进程传给子进程。不管子进程的环境变量如何变化,都不会影响父进程的环境变量。
shell script:
有两种方法执行shell scripts,一种是新产生一个shell,然后执行相应的shell
scripts;一种是在当前shell下执行,不再启用其他shell。
新产生一个shell然后再执行scripts的方法是在scripts文件开头加入以下语句#!/bin/sh。
一般的script文件(.sh)即是这种用法。这种方法先启用新的sub-shell(新的子进程),然后在其下执行命令。
另外一种方法就是上面说过的source命令,不再产生新的shell,而在当前shell下执行一切命令。
source:
source命令即点(.)命令。在bash下输入man source,找到source命令解释处,可以看到解释"Read and execute commands from filename in the current
Shell脚本实现Linux系统定时任务调度
Shell脚本实现Linux系统定时任务调度
一、介绍
在Linux系统中,为了实现自动化任务调度,我们可以使用Shell脚本来编写定时任务。Shell脚本是一种逐行解释执行的脚本语言,结合Linux系统提供的定时任务调度器,可以实现多种任务的定时执行。
二、Shell脚本基础
1. Shell脚本的创建与执行
Shell脚本文件以.sh为后缀,可以使用任意文本编辑器创建和编辑。为了执行Shell脚本,首先需要给脚本文件添加可执行权限,使用chmod命令进行修改,如下所示:
```
chmod +x script.sh
```
然后,可以使用以下命令执行Shell脚本:
```
./script.sh
```
2. Shell脚本的语法 Shell脚本的语法基本与Bash Shell相同,可以使用条件语句、循环语句、函数等实现复杂的逻辑。下面是一个简单的示例:
```
#!/bin/bash
# 打印当前系统时间
echo "当前时间为:"
date
```
以上示例使用了echo命令打印输出,并通过date命令获取系统当前时间。
三、定时任务调度器
Linux系统提供了多种定时任务调度器,常用的有cron和at。
1. cron
cron是Linux系统上常用的定时任务调度器,它可以按照用户指定的时间间隔周期性地执行任务。cron将定时任务的信息存储在一个称为crontab的表中,用户可以编辑、查询和删除任务。
2. at
at是另一个常用的定时任务调度器,它允许用户在一次性的任务中指定一个具体的执行时间。at的任务调度信息会被存储在一个队列中,系统将在指定的时间执行任务。 四、Shell脚本实现定时任务调度
1. 使用cron调度任务
使用cron调度任务需要编辑crontab表。可以使用以下命令编辑当前用户的crontab表:
```
crontab -e
```
然后,在打开的编辑器中添加任务的调度信息。例如,为每天的上午10点执行一个任务,可以添加以下行:
