(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番目のインデックスで終了すると、$memp(メモリ使用率)値を表示せずに$ process_string変数を印刷します。これは、すべての$ 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を解析しないでください
  • 同じ$ pid / statファイル内の他のフィールドから複数回呼び出すのではなく、次のようにawk | read使用します。awk
  • cat | grep | awkただawk行う場所では使用しないでください
  • 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

関連情報