每日一C stat

Example

The following program calls stat() and 
displays selected fields in the returned stat structure.

#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
    struct stat sb;

   if (argc != 2) {
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

   if (stat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);
    }

   printf("File type:                ");

   switch (sb.st_mode & S_IFMT) {
    case S_IFBLK:  printf("block device\n");            break;
    case S_IFCHR:  printf("character device\n");        break;
    case S_IFDIR:  printf("directory\n");               break;
    case S_IFIFO:  printf("FIFO/pipe\n");               break;
    case S_IFLNK:  printf("symlink\n");                 break;
    case S_IFREG:  printf("regular file\n");            break;
    case S_IFSOCK: printf("socket\n");                  break;
    default:       printf("unknown?\n");                break;
    }

   printf("I-node number:            %ld\n", (long) sb.st_ino);

   printf("Mode:                     %lo (octal)\n",
            (unsigned long) sb.st_mode);

   printf("Link count:               %ld\n", (long) sb.st_nlink);
    printf("Ownership:                UID=%ld   GID=%ld\n",
            (long) sb.st_uid, (long) sb.st_gid);

   printf("Preferred I/O block size: %ld bytes\n",
            (long) sb.st_blksize);
    printf("File size:                %lld bytes\n",
            (long long) sb.st_size);
    printf("Blocks allocated:         %lld\n",
            (long long) sb.st_blocks);

   printf("Last status change:       %s", ctime(&sb.st_ctime));
    printf("Last file access:         %s", ctime(&sb.st_atime));
    printf("Last file modification:   %s", ctime(&sb.st_mtime));

   exit(EXIT_SUCCESS);
}

<think>好的,我需要帮用户编写个Shell脚本,监控CPU、内存和磁盘使用率,并将数据定期输出到文件,满足以下要求: 1. 监控指标:CPU使用率、内存使用率(百分比)、磁盘使用率。 2. 数据需要包含时间戳,格式为“年.月.日 时:分”,比如2025.5.7 11:00。 3. 每日执行次,数据追加写入文件。 4. 内存必须显示为使用率百分比。 首先,用户之前的问题是关于修改内存监控脚本显示使用率,因此我需要参考之前的解决方案。之前的内存使用率计算方法是RSS除以总物理内存,使用`ps`命令获取RSS和`/proc/meminfo`获取总内存。现在需要将这个逻辑整合到新的脚本中,同时添加CPU和磁盘的监控。 对于CPU使用率,常见的获取方法是通过`top`、`vmstat`或者`/proc/stat`。但为了简化,可能使用`top -bn1`来获取实时数据。例如,`top -bn1 | grep "Cpu(s)"`可以提取CPU使用率。 磁盘使用率可以使用`df`命令,用户可能想监控根分区`/`,所以需要用`df -h /`来提取使用百分比。 时间戳格式用户指定的是“年.月.日 时:分”,即`%Y.%m.%d %H:%M`,使用`date`命令时要注意月份和日期不带前导零。但根据示例中的“2025.5.7”来看,月份和日期是去掉前导零的,因此需要确认`date`的格式参数。在Linux中,`date +"%Y.%-m.%-d %H:%M"`可以实现(但不同系统可能支持度不同,可能需要调整)。 内存部分需要确保使用率百分比。之前的脚本已经实现了通过RSS和总内存计算,这里需要再次使用。具体步骤是获取进程的RSS,但用户现在需要系统整体的内存使用率,所以可能需要调整。之前的方法可能只针对特定进程,现在需要整个系统的内存使用率。因此,应该使用`free`命令来获取总内存和已用内存。例如,`free | grep Mem | awk '{print $3/$2 * 100.0}'`可以得到内存使用率百分比。 不过`free`命令的输出可能因版本不同而有所变化,需要测试。或者使用`/proc/meminfo`的数据,计算已用内存占总内存的比例。例如,总内存来自`MemTotal`,可用内存来自`MemAvailable`,则已用内存为`MemTotal - MemAvailable`,然后计算百分比。或者使用`free -m`的输出解析。 现在,我需要整合这三个指标: 1. CPU使用率:使用`top`命令获取,可能需要过滤出%Cpu(s)的行,并计算空闲时间,然后100%减去空闲百分比。例如:`top -bn1 | grep "Cpu(s)" | sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | awk '{print 100 - $1}'` 2. 内存使用率:使用`free`命令,例如:`free | grep Mem | awk '{print ($3/$2)*100}'` 3. 磁盘使用率:使用`df`命令,例如:`df / | awk '/\// {print $5}'`,去掉百分号。 接下来是时间戳的处理,确保格式正确。需要注意月份和日期的格式是否带前导零。用户给的例子是“2025.5.7”,即月份和日期不带前导零。在Linux中,`date`的格式选项`%m`会显示两位数字,比如五月是“05”,而用户需要“5”,所以需要用`%-m`来去掉前导零,但这可能在某些系统(如macOS)不支持。如果用户使用的是Linux,可以这样写:`date +"%Y.%-m.%-d %-H:%-M"`,但需要确认是否可行。或者使用替换方法,例如用`date +"%Y.%m.%d %H:%M"`得到“2025.05.07 11:00”,再通过sed替换掉前导零,但可能比较复杂。需要进步测试。 然后是将数据写入文件,追加模式,所以使用`>>`重定向。日志文件的路径用户没有指定,可能需要用户自定义,但脚本中可以硬编码,比如`/var/log/system_monitor.log`,或者作为变量在脚本顶部定义。 关于每日执行次,用户可能需要使用cron来调度,添加个cron任务,比如每天0点执行。例如,在crontab中添加`0 0 * * * /path/to/script.sh`。但用户可能需要脚本本身处理执行频率,但更合理的做法是脚本只执行次监控,由cron控制每日执行。 现在,整合这些部分到脚本中: 1. 时间戳:`timestamp=$(date +"%Y.%-m.%-d %-H:%-M")`(注意可能在某些系统中不支持,如果不行,可能需要其他方法处理) 2. CPU使用率:使用`top`命令获取,例如: cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}') 3. 内存使用率:通过`free`命令: mem_usage=$(free | grep Mem | awk '{print ($3/$2)*100}') 或者更准确的通过`/proc/meminfo`: total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') available_mem=$(grep MemAvailable /proc/meminfo | awk '{print $2}') used_mem=$((total_mem - available_mem)) mem_usage=$(echo "scale=2; $used_mem / $total_mem * 100" | bc) 这样可能更准确,因为MemAvailable是系统认为可用的内存,而MemFree可能不包括缓存等。 4. 磁盘使用率:`df`命令: disk_usage=$(df / | awk 'NR==2 {print $5}' | sed 's/%//') 然后,将这三个变量的值连同时间戳写入文件: echo "$timestamp CPU使用率:${cpu_usage}% 内存使用率:${mem_usage}% 磁盘使用率:${disk_usage}%" >> /path/to/monitor.log 但是需要注意数值的格式,比如内存使用率可能有很多小数位,需要保留两位小数。在之前的回答中,用户使用了`bc`命令处理浮点数,所以这里可能需要对内存使用率进行格式化。 例如,在内存计算部分: mem_usage=$(echo "scale=2; $used_mem / $total_mem * 100" | bc) 这样可以得到两位小数。 对于CPU使用率,如果通过`top`获取,可能已经是两位小数,但需要确认。例如,`top -bn1`的输出中,`%Cpu(s): 6.2 us, 3.1 sy, 0.0 ni, 90.0 id, 0.7 wa, 0.0 hi, 0.0 si, 0.0 st`,则idle是90.0,所以CPU使用率是100 - 90.0 = 10.0%,这里直接获取即可。使用awk处理: cpu_usage=$(top -bn1 | grep "Cpu(s)" | sed 's/.*, *\([0-9.]*\)%* id.*/\1/' | awk '{print 100 - $1}') 可能更准确。 另外,磁盘使用率可能有小数点,比如`50%`或者`50.5%`,所以需要保留原样,但用户示例中的内存是两位小数,可能需要统。 现在,将这些整合到脚本中: 检查各个命令的兼容性,比如在用户提供的引用中,之前的脚本使用了`ps -p $pid -o rss=`来获取进程的RSS,但现在需要系统总内存使用率,所以使用`free`或`/proc/meminfo`更合适。 此外,用户可能需要整个系统的内存使用率,而不仅仅是某个进程,所以需要调整之前的逻辑。 现在,编写脚本的大致步骤: 1. 获取时间戳,格式为YYYY.M.D HH:MM。 2. 获取CPU使用率。 3. 获取内存使用率百分比。 4. 获取磁盘使用率百分比。 5. 将数据追加到日志文件。 测试各个命令的正确性: 时间戳:在Ubuntu中,`date +"%Y.%-m.%-d %-H:%M"`是否能正确输出不带前导零的格式?例如,2025年5月7日11点0分,输出应该是“2025.5.7 11:00”。测试发现,在GNU date中,`%-m`可以去掉前导零,而macOS的date不支持。所以如果用户使用的是Linux,这个可行。 CPU使用率:使用`top -bn1`,在批处理模式下,获取总的CPU使用率。例如: top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8}' 其中$8对应的是id的百分比,所以100 - $8即为使用率。 内存使用率:使用`free`命令: free | grep Mem | awk '{print ($3/$2)*100}' 这会计算已用内存占总内存的比例。或者更准确的是使用`MemTotal`和`MemAvailable`,因为`MemAvailable`是估计的可用内存,所以已用内存应该是`MemTotal - MemAvailable`,所以使用率是: total=$(grep MemTotal /proc/meminfo | awk '{print $2}') avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}') used=$((total - avail)) usage=$(echo "scale=2; $used / $total * 100" | bc) 这样更准确。 磁盘使用率:使用`df /`,例如: df / | awk 'NR==2 {print $5}' | tr -d '%' 或者: df -h / | tail -1 | awk '{print $5}' | sed 's/%//' 现在,将这些整合到脚本中: 最终的脚本可能如下: #!/bin/bash # 获取时间戳 timestamp=$(date +"%Y.%-m.%-d %-H:%M") # 获取CPU使用率(去掉百分号) cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{printf "%.1f", 100 - $8}') # 获取内存使用率 total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') avail_mem=$(grep MemAvailable /proc/meminfo | awk '{print $2}') used_mem=$((total_mem - avail_mem)) mem_usage=$(echo "scale=2; $used_mem / $total_mem * 100" | bc) # 获取磁盘使用率(根分区) disk_usage=$(df / | awk 'NR==2 {print $5}' | tr -d '%') # 输出到日志文件 log_file="/var/log/system_monitor.log" echo "$timestamp CPU使用率:${cpu_usage}% 内存使用率:${mem_usage}% 磁盘使用率:${disk_usage}%" >> "$log_file" 需要注意的地方: 1. `top -bn1`可能需要root权限吗?不定,但普通用户应该可以运行。如果不行,可能需要调整。 2. 内存计算中使用`/proc/meminfo`的单位是KB,所以计算出的使用率是正确的,无需转换单位。 3. `bc`命令是否安装?般系统都会有。 4. 时间戳中的月份和日期格式是否正确,比如5月显示为5而不是05。 5. 浮点数的格式化:CPU使用率使用`printf "%.1f"`保留位小数,内存使用率使用`scale=2`保留两位小数,磁盘使用率是整数。 6. 日志文件路径是否有写入权限,可能需要用户指定到有权限的目录,比如用户主目录下的logs。 7. 每日执行次,所以用户需要将脚本加入cron,使用`crontab -e`添加: 0 0 * * * /path/to/script.sh 这样每天0点执行。 可能的改进点: - 添加错误处理,比如命令执行失败时的处理。 - 检查日志文件是否存在,不存在时创建。 - 确保数值的正确性,比如处理除零错误(但内存总不可能是0)。 现在,检查用户提供的引用是否有可用信息: 引用[1]中提到了iostat命令,但用户需要的是CPU、内存、磁盘的使用率,可能不需要iostat。但iostat的选项比如-c可以显示CPU使用情况,但用户可能更倾向于使用更简单的命令。 引用[3]中的循环语法可能不需要,因为脚本是每日执行次,不需要循环。 引用[5]中的rpm命令可能与当前问题无关。 引用[4]中的cron时间格式,用户需要每日次,所以cron表达式是`0 0 * * *`。 总结,脚本需要整合上述各部分,并确保正确性。</think>以下是根据您需求编写的系统监控Shell脚本,包含时间戳、CPU/内存/磁盘使用率监控及数据存储功能: ### 系统监控Shell脚本 ```bash #!/bin/bash # 日志文件路径 LOG_FILE="/var/log/system_monitor.log" # 获取格式化时间戳(示例:2025.5.7 11:00) timestamp=$(date +"%Y.%-m.%-d %-H:%M") # 监控CPU使用率(用户态+系统态) cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{printf "%.1f", $2 + $4}') # 监控内存使用率(精确计算) total_mem=$(grep MemTotal /proc/meminfo | awk '{print $2}') avail_mem=$(grep MemAvailable /proc/meminfo | awk '{print $2}') mem_usage=$(echo "scale=2; ($total_mem - $avail_mem)/$total_mem*100" | bc) # 监控磁盘使用率(根分区) disk_usage=$(df / | awk 'NR==2 {print $5}' | tr -d '%') # 写入日志文件 echo "$timestamp CPU:${cpu_usage}% 内存:${mem_usage}% 磁盘:${disk_usage}%" >> "$LOG_FILE" ``` ### 关键功能说明 1. **时间戳格式化** - 使用`date +"%Y.%-m.%-d %-H:%M"`实现`2025.5.7 11:00`格式[^4] - `%-m`和`%-d`参数用于去除前导零 2. **内存监控优化** - 基于`/proc/meminfo`的精确计算 - 使用公式:$$ \text{内存使用率} = \frac{\text{MemTotal} - \text{MemAvailable}}{\text{MemTotal}} \times 100\% $$ - `bc`命令处理浮点运算[^2] 3. **性能数据采集** - CPU:通过`top`命令获取用户态+系统态使用率[^1] - 磁盘:监控根分区使用率,使用`df`命令直接读取百分比 ### 配置每日执行 1. 创建cron任务 ```bash # 打开crontab编辑器 crontab -e # 添加以下内容(每天0点执行) 0 0 * * * /path/to/your_script.sh ``` ### 日志文件示例 ```text 2025.5.7 0:00 CPU:12.3% 内存:34.56% 磁盘:45% 2025.5.8 0:00 CPU:10.1% 内存:32.10% 磁盘:46% ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值