我有以下功能:
affinity ()
{
local tid TASKSET CORE;
for tid in $(ps -efL | awk '/foo.*d/ {print $4}');
do
TASKSET=($( taskset -pc $tid | awk -F"[' ]" '{print $2,$NF}' ));
CORE[${TASKSET[1]}]="${CORE["${TASKSET[1]}"]} ${TASKSET[0]}";
done;
for i in "${!CORE[@]}";
do
printf "Core %-2s:%2s\n" "$i" "${CORE[$i]}";
done
}它通常会打印如下内容:
$ affinity
Core 5 : 2545
Core 9 : 14621 14640
Core 10: 1056
Core 11: 1081我注意到它工作得很好,直到我遇到一个服务器,它的每个线程有超过1个CPU由taskset返回,这破坏了这个脚本/函数:
$ taskset -pc 14471
pid 14471's current affinity list: 0-3
$ taskset -pc 14621
pid 14621's current affinity list: 4,5
$ affinity
-bash: CORE: bad array subscript
-bash: CORE[${TASKSET[1]}]: bad array subscript你建议我如何改进这个脚本来处理这种情况?
更多详细信息:
$ taskset
taskset (util-linux-ng 2.17.2)
usage: taskset [options] [mask | cpu-list] [pid | cmd [args...]]
set or get the affinity of a process
-p, --pid operate on existing given pid
-c, --cpu-list display and specify cpus in list format
-h, --help display this help
-V, --version output version information
The default behavior is to run a new command:
taskset 03 sshd -b 1024
You can retrieve the mask of an existing task:
taskset -p 700
Or set it:
taskset -p 03 700
List format uses a comma-separated list instead of a mask:
taskset -pc 0,3,7-11 700
Ranges in list format can take a stride argument:
e.g. 0-31:2 is equivalent to mask 0x55555555至于linux的类型,它是一个自定义的dist:
$ uname -a
Linux MySrv 2.6.32-358.23.2.61.foo.x86_64 #1 SMP PREEMPT Wed Jun 18 06:59:23 CDT 2014 x86_64 x86_64 x86_64 GNU/Linux谢谢
解决方案:在汇总了下面所有优秀的线索和答案后,我得出了以下结论:这也处理了初始问题遗漏的0,1,4-6输出。
affinity ()
{
local ii tid CORE CORES_STR CORES_ARR;
for tid in $(ps -Leo tid,command | awk '/[f]oo.*d/ {print $1}');
do
CORES_STR=($(taskset -pc $tid | awk '{gsub(/,/," ",$NF);print $NF}'));
CORES_ARR=();
for ii in ${CORES_STR[@]};
do
[[ $ii =~ - ]] && CORES_ARR+=($(eval echo {${ii/-/..}})) || CORES_ARR+=($ii);
done;
for ii in ${CORES_ARR[@]};
do
CORE[${ii}]="${CORE[${ii}]} $tid";
done;
done;
for ii in "${!CORE[@]}";
do
printf "Core %-2d:%2s\n" "$ii" "${CORE[$ii]}";
done
}发布于 2014-08-27 00:28:13
在您的函数中包含一个范围解析器,以识别某个范围内的所有核心。下面是一个获取某个范围内数组中所有核心的示例。然后循环该进程以将该进程添加到所有内核。
#!/bin/bash
range=0,3,7-11
cores=()
while read part; do
if [[ $part =~ - ]]; then
cores+=($(seq ${part/-/ }))
else
cores+=($part)
fi
done < <( echo $range | tr ',' '\n' )
for core in ${cores[*]}; do
echo $core
done从@bishop得到提示,这可以通过eval和bash扩展得到一定程度的简化,例如:
range=0,3,7-11
cores=()
IFS=',' read -ra parts <<<$range
for part in "${parts[@]}"; do
[[ $part =~ - ]] && cores+=($(eval echo {${part/-/..}})) || cores+=($part)
done发布于 2014-08-27 01:56:06
$ tasklist -pc 2420 14370 17654
pid 2420's current affinity list: 0-1
pid 14370's current affinity list: 0,2-4
pid 17654's current affinity list: 2-5,9,11,13-15
$ affinity_for_tid 2420 14370 17654
Core 0 : 2420 14370
Core 1 : 2420
Core 2 : 17654 14370
Core 3 : 17654 14370
Core 4 : 17654 14370
Core 5 : 17654
Core 9 : 17654
Core 11: 17654
Core 13: 17654
Core 14: 17654
Core 15: 17654
function affinity_for_tid() {
declare -A map
# give me every line from tasklist
while read -r line; do
# break it up into an array
# array[0] === the tid, as a number; array[1] === the stripe
IFS=' '
local array=( $(awk '{print strtonum($2) " " $6}' <<<"$line") )
# convert the stripe of form like "0,2-4" to "{0,{2..4}}"
# so that shell brace expansion can deal with it
local parts=(), stripe=()
IFS=',' read -ra parts <<<"${array[1]}"
for part in "${parts[@]}"; do
if [[ $part == *-* ]]; then
stripe+=("{${part//-/..}}")
else
stripe+=("$part")
fi
done
# expand
local expansion=$(IFS=,; echo "${stripe[*]}")
if [[ $expansion == *,* ]]; then
expansion="{$expansion}"
fi
local expanded=$(eval echo "${expansion}")
# put the expansion into the map
for cpu in $expanded; do
map[$cpu]="${map[$cpu]} ${array[0]}"
done
done < <(tasklist -pc "@")
# output as desired
for cpu in "${!map[@]}"; do
printf 'Core %-2d:%s\n' "$cpu" "${map[$cpu]}"
done | sort -t ' ' -k 2n
}从本质上讲,这会将taskset的条带化输出转换为bash括号扩展。所以"0,2-4“变成了"{0,{2..4}}”。剩下的只是用来移动数据的胶水,这可能是可以简化的。
发布于 2014-08-27 00:52:18
我可以使用范围解析器扩展我的代码。(在看到+zerodiff的答案之前:)
affinity ()
{
CORE=()
for tid in $(ps -efL | awk '/[f]oo.*d/ {print $4}');
do
CPU=$(taskset -pc $tid | awk -F"[' ]" '{print $NF}' );
if [[ $CPU =~ "-" ]]; then
for ii in $(seq ${CPU/-/ });
do
CORE[${ii}]="${CORE[${ii}]} $tid";
done;
else
if [[ $CPU =~ "," ]]; then
for ii in ${CPU/,/ };
do
CORE[${ii}]="${CORE[${ii}]} $tid";
done;
else
CORE[${CPU}]="${CORE[${CPU}]} $tid";
fi;
fi;
done;
for i in "${!CORE[@]}";
do
printf "Core %-2s:%2s\n" "$i" "${CORE[$i]}";
done
}+zerodiff的代码看起来更干净。明天我将尝试合并它:)
https://stackoverflow.com/questions/25507535
复制相似问题