shell与c语言完美结合,解析 df -h 命令中的 /dev/sd* 外设设备使用情况

shell与c语言完美结合,解析 df -h 命令中的 /dev/sd* 外设设备使用情况

1. 查看 /dev/sd* 设备的使用情况

在Linux系统下使用 df -h 获取系统挂载的设备信息,然后找到设备关键名称为 “/dev/sd” 开头的行,如:

df -h # -h 表示使用带单位的显示方式

结果如下:

Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                       17G  7.4G  8.6G  47% /
/dev/sda1              99M   12M   82M  13% /boot
tmpfs                1014M     0 1014M   0% /dev/shm
/dev/sdb1             2.0G   36M  1.9G   2% /home/newdisk
.host:/                30G   15G   16G  49% /mnt/hgfs

2. shell命令获取设备名称,大小,已用空间和可用空间的信息

使用shell命令的管道,grep和awk命令,解析 /dev/sd* 设备的信息,如:

df -h | grep -rns "/dev/sd[a-z]*"  # 表示搜索关键字开头 sda 到 sdz 开头的设备 

执行上面的结果输出如下:

4:/dev/sda1              99M   12M   82M  13% /boot
6:/dev/sdb1             2.0G   36M  1.9G   2% /home/newdisk

可以看到,设备名称 /dev/sda1 前面有一个 4/6和冒后(:)内容,这个是我们不需要的,原因在于我们使用grep是带了 -n 参数,表示行号。因此,修改如下即可:

df -h | grep -rs "/dev/sd[a-z]*"

结果如下:

/dev/sda1              99M   12M   82M  13% /boot
/dev/sdb1             2.0G   36M  1.9G   2% /home/newdisk

以上的结果便是我们解析出来的设备信息。

但以上的信息,我们只是需要设备名称,大小,已用空间和可用空间的信息,其他信息可以省略,因此使用awk命令输出 前4列 信息即可。即

df -h | grep -rs "/dev/sd[a-z]*" | awk '{print $1,$2,$3,$4}'

结果如下:

/dev/sda1 99M 12M 82M
/dev/sdb1 2.0G 36M 1.9G

3. 使用c语言结合获取设备信息

在第二步中我们已经获取到相应的设备信息,现在我们需要在 c语言上进行读取,实际上我们把第二步的 shell 命令 重定向 到一个文本上,然后利用读取文本的方式,解析出我们需要的数据。shell命令如下:

df -h | grep -rs "/dev/sd[a-z]*" | awk '{print $1,$2,$3,$4}' > 1.txt
3.1 c 语言执行 shell 命令,常规使用的有 system/popen/excel

在测试中,上述三个函数,无论使用任意一个,都是可以的,但在实际应用中,仍然需要根据实际进行选择,读者自行查询资料。 本次我们使用 popen 函数进行测试。

3.2 c语言重定向的 shell 字符串命令
// shell 字符串命令
#define redirect_name "1.txt"
#define get_disk_cmd "df -h | grep -rs \"/dev/sd[a-z]*\" | awk '{print $1,$2,$3,$4}' > " redirect_name
3.3 使用 popen 函数

3.3.1 popen 函数原型:

#include <stdio.h>

FILE *popen(const char *command, const char *type);

int pclose(FILE *stream);

也就是说,使用 popen 执行的shell命令,返回的是一个 FILE* 的文件操作指针,也需要使用 pclose 关闭,而不是使用 fclose 关闭。

command:   传入的为 shell 命令
   type:   命令的操作类型,读出("r") / 写入("w")   
   返回:   FILE 类型的文件指针。

具体使用如下:

FILE *fp = NULL;

fp = popen(get_disk_cmd, "r");

if(fp == NULL)
{
	return -1;
}

pclose(fp);
fp = NULL;

3.4 使用 fopen/fgets/fclose/ssanf 函数读取重定向文件,获取数据
FILE *fp = NULL;

fp = fopen(redirect_name, "r");

if(fp == NULL)
{
	return -1;
}


while(fgets(disk_info, 256, fp))
{
	memset(disk_name, '\0', sizeof(disk_name));
	memset(disk_size, '\0', sizeof(disk_size));
	memset(disk_used_size, '\0', sizeof(disk_used_size));
	memset(disk_avail_size, '\0', sizeof(disk_avail_size));

	sscanf(disk_info, "%[^ ] %[^ ] %[^ ] %[^\n]",            \
	                  disk_name, disk_size,                  \
					  disk_used_size,disk_avail_size);

	printf("name: %s\t\tsize: %s\tnused: %s\tavail: %s\r\n", \
	                  disk_name, disk_size,                  \
				      disk_used_size, disk_avail_size);

}

fclose(fp);
fp = NULL;

我们使用 sscanf 函数的正则表达式来进行获取数据,也可以直接使用 %s 格式来获取,但有可能读取越界。

sscanf(disk_info, "%s %s %s %s\n",            \
	                  disk_name, disk_size,                  \
					  disk_used_size,disk_avail_size);
3.5 完整代码
#include <stdio.h>
#include <string.h>

#define redirect_name "1.txt"

#define get_disk_cmd "df -h | grep -rs \"/dev/sd[a-z]*\" | awk '{print $1,$2,$3,$4}' > " redirect_name

int main(int argc, char const *argv[])
{

	FILE *fp = NULL;
	char disk_info[256] = {'\0'};
	char disk_name[128] = {'\0'};
	char disk_size[32] = {'\0'};
	char disk_used_size[32] = {'\0'};
	char disk_avail_size[32] = {'\0'};

	fp = popen(get_disk_cmd, "r");

	if(fp == NULL)
	{
		return -1;
	}

	pclose(fp);
	fp = NULL;


	fp = fopen(redirect_name, "r");

	if(fp == NULL)
	{
		return -1;
	}


	while(fgets(disk_info, 256, fp))
	{
		memset(disk_name, '\0', sizeof(disk_name));
		memset(disk_size, '\0', sizeof(disk_size));
		memset(disk_used_size, '\0', sizeof(disk_used_size));
		memset(disk_avail_size, '\0', sizeof(disk_avail_size));
	
		sscanf(disk_info, "%[^ ] %[^ ] %[^ ] %[^\n]",            \
		                  disk_name, disk_size,                  \
						  disk_used_size,disk_avail_size);

		printf("name: %s\t\tsize: %s\tnused: %s\tavail: %s\r\n", \
		                  disk_name, disk_size,                  \
					      disk_used_size, disk_avail_size);
	
	}

	fclose(fp);
	fp = NULL;

	return 0;
}

输出结果如下,与我们在终端窗口使用shell命令一样:

name: /dev/sda1		size: 99M	nused: 12M	avail: 82M
name: /dev/sdb1		size: 2.0G	nused: 36M	avail: 1.9G

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值