(standard_in) 循环 for 循环时出现非法字符

(standard_in) 循环 for 循环时出现非法字符

我正在尝试获取与进程和一般系统信息相关的统计信息。如果我在不循环的情况下执行此操作,它运行得很好,但如果我将它放在循环中,它只会给我带来非法字符的连锁错误。

#!/bin/bash
TOTALMEM=$(awk '{ print $1 }' /proc/meminfo)
l=$(ls /proc | grep '[0-9]$')

for pid in $l
do
    PID=$pid
    cmd=$(cat /proc/$PID/cmdline)
    state=$(awk '{ print $3 }' /proc/$PID/stat)
    utime=$(awk '{ print $14 }' /proc/$PID/stat)
    stime=$(awk '{ print $15 }' /proc/$PID/stat)
    pr=$(awk '{ print $18 }' /proc/$PID/stat)
    state=$(awk '{ print $3 }' /proc/$PID/stat) 
    ttime=$(($utime+$stime))
    mem=$(cat /proc/$PID/status | grep VmSize: | awk '{ print $2 }')
    memp=$(echo "scale=2;$TOTALMEM / $mem" | bc -l)
    memp="$memp%"
    mem=$(echo "scale=2;$mem / 1024" | bc -l)
    cpu=$ttime
    usr=$(stat -c '%U' /proc/$PID)

    process_string="$PID $usr $pr $mem $state $cpu $memp $ttime $cmd"
    echo $process_string
done

这是提示错误的示例。一切都像这样(随机字符给出错误),为每个索引(从 1 到 44)重复很多次。

(standard_in) 1: illegal character: M
(standard_in) 1: illegal character: T
(standard_in) 1: syntax error
(standard_in) 1: illegal character: :

一旦它在第 44 个索引处结束,它就会打印变量 $process_string,而不显示 $memp(内存百分比使用率)值。这似乎发生在每个 $pid (进程)上。

如果我将它放入 for 循环中,它就会中断,但如果我不这样做,它就不会中断,而且我不知道为什么它会这样工作。

答案1

您可能希望第一个作业更像这样:

TOTALMEM=$(awk '{ print $2 }' /proc/meminfo | head -n 1)

否则你会在这一行中得到很多值(不带引号):

memp=$(echo "scale=2;$TOTALMEM / $mem" | bc -l)

awk 的更好用法是匹配您正在寻找的实际标签,例如,

TOTALMEM=$(awk '/^MemTotal:/ { print $2 }' /proc/meminfo | head -n 1) 

答案2

试试这个,它有一些错误修复和速度改进,包括:

  • 不解析 ls
  • 使用awk | read而不是awk对同一 $pid/stat 文件的不同字段多次调用
  • 不使用cat | grep | awkwhere just awkwill do
  • 跳过没有 VMSize 的条目。

请注意有关 VmSize 的注释 - 它会跳过所有没有 VmSize 条目的过程。在这些情况下,您可能需要使用其他方法来确定“$mem”,而不是仅仅跳过。

#!/bin/bash

TOTALMEM=$(awk '/^MemTotal:/ { print $2 }' /proc/meminfo)

for pid in /proc/[0-9]* ; do
    PID=$(basename $pid)
    cmd=$(cat $pid/cmdline)

    # use `awk | read` to avoid multiple calls to awk
    awk '{print $3,$14,$15,$18}' $pid/stat | read state utime stime pr


    ttime=$((utime + stime))

    # not all procs have a VmSize entry in status
    mem=$(awk '/VmSize:/ { print $2 }' $pid/status)

    # empty "$mem" causes a syntax error in bc
    if [ -n "$mem" ] ; then
      memp=$(echo "scale=2;$TOTALMEM / $mem" | bc -l)
      memp="$memp%"

      mem=$(echo "scale=2;$mem / 1024" | bc -l)
      cpu=$ttime
      usr=$(stat -c '%U' $pid)

      process_string="$PID $usr $pr $mem $state $cpu $memp $ttime $cmd"
      echo $process_string
    fi

done

相关内容