如何使用shell迭代Linux cpuset?

时间:2018-05-19 22:26:25

标签: linux bash shell sysfs

Linux的sys文件系统表示一组CPU ID,语法为:

  1. 0,2,8:包含0,2和8的CPU集。
  2. 4-6:包含4,5和6的CPU集。
  3. 两种语法都可以混合和匹配,例如:0,2,4-6,8
  4. 例如,在我的机器上运行cat /sys/devices/system/cpu/online打印0-3,这意味着CPU 0,1,2和3在线。

    问题是上面的语法很难在shell脚本中使用for循环进行迭代。如何将上述语法转换为更传统的语法,例如0 2 4 5 6 8

3 个答案:

答案 0 :(得分:0)

尝试:

$ echo 0,2,4-6,8 | awk '/-/{for (i=$1; i<=$2; i++)printf "%s%s",i,ORS;next} 1' ORS=' ' RS=, FS=-
0 2 4 5 6 8

这可以在循环中使用如下:

for n in $(echo 0,2,4-6,8 | awk '/-/{for (i=$1; i<=$2; i++)printf "%s%s",i,ORS;next} 1' RS=, FS=-)
do
   echo cpu="$n"
done

产生输出:

cpu=0
cpu=2
cpu=4
cpu=5
cpu=6
cpu=8

或者喜欢:

printf "%s" 0,2,4-6,8 | awk '/-/{for (i=$1; i<=$2; i++)printf "%s%s",i,ORS;next} 1' RS=, FS=- | while read n
do
   echo cpu="$n"
done

还产生:

cpu=0
cpu=2
cpu=4
cpu=5
cpu=6
cpu=8

如何运作

awk命令的工作原理如下:

  • RS=,

    这告诉awk使用,作为记录分隔符。

    例如,如果输入为0,2,4-6,8,则awk会看到四条记录:02以及4-68

  • FS=-

    这告诉awk使用-作为字段分隔符。

    FS设置此方式,例如,如果输入记录包含2-4,则awk会将2视为第一个字段,将4视为/-/{for (i=$1; i<=$2; i++)printf "%s%s",i,ORS;next}第二场。

  • -

    对于包含$1的任何记录,我们会打印出每个数字,以第一个字段$2的值开头,并以第二个字段ORS的值结尾。每个这样的数字后跟输出记录分隔符ORS。默认情况下,ORS是换行符。对于上面的一些示例,我们将next设置为空白。

    打印完这些数字后,我们跳过其余的命令并跳转到1记录。

  • -

    如果我们到达此处,则该记录不包含1,我们按原样打印出来。 vw是awk的简写版本。

答案 1 :(得分:0)

Perl one:

echo "0,2,4-6,8" | perl -lpe 's/(\d+)-(\d+)/{$1..$2}/g; $_="echo {$_}"' | bash

只需将原始字符串转换为echo {0,2,{4..6},8},然后让bash&#39;支持扩展&#39;插入它。

答案 2 :(得分:-1)

eval echo $(cat /sys/devices/system/cpu/online | sed 's/\([[:digit:]]\+\)-\([[:digit:]]\+\)/$(seq \1 \2)/g' | tr , ' ')

说明:

  1. cat /sys/devices/system/cpu/online从sysfs中读取文件。这可以更改为任何其他文件,例如offline
  2. 输出通过替换s/\([[:digit:]]\+\)-\([[:digit:]]\+\)/$(seq \1 \2)/g传送。这与4-6类似,并将其替换为$(seq 4 6)
  3. tr , ' '用空格替换所有逗号。
  4. 此时,输入0,2,4-6,8将转换为0 2 $(seq 4 6) 8。最后一步是eval此序列获取0 2 4 5 6 8
  5. 示例echo是输出。或者,它可以写入变量或用于for循环。