0

I need to fix the following piece of code. The code aims to determine the number of cores available in a given node.

Step 1: Get the number of cores with

TC=$(grep -c process /proc/cpuinfo)

Step 2: Take the uptime ignoring the decimals

LA=$(uptime | cut -d ' ' -f 13 | head -c 1)

Step 3: Subtract $LA from $TC to get the number of processes I can run

procs=$(expr $TC - $LA)

My issue is with Step 2: when I type uptime | cut -d ' ' -f 13 | head -c 1, I get a. What does that mean? Is there a mistake in step 2?

Let me add that if I type simply uptime I get

 23:17:01 up 38 days, 38 min,  8 users,  load average: 0.00, 0.00, 0.00
1

The output of uptime includes several fields with a variable numbers of spaces. cut treats every space as a field separator, so changes to some of those values will mean your cut pulls out a different number entirely.

For example, the number of users is space-padded. When it's less than 10, there are two spaces; when 10 or more, only 1.

$ echo ' 23:17:01 up 38 days, 38 min,  8 users,  load average: 0.00, 0.00, 0.00'|cut -d ' ' -f13
average:
$ echo ' 23:17:01 up 38 days, 38 min, 10 users,  load average: 0.00, 0.00, 0.00'|cut -d ' ' -f13
0.00,

You could instead use awk, which permits a variable amount of space between each field (and ignores space at the beginning of the line):

$ echo ' 23:17:01 up 38 days, 38 min,  8 users,  load average: 0.00, 0.00, 0.00' | awk '{print $11}'

But this can still break if the number of "words" itself changes, eg. when the uptime itself isn't (just) days and minutes:

 14:51:24 up 4 min,  1 user,  load average: 0.17, 0.16, 0.07
 14:52:09 up 6 days, 21:58, 11 users,  load average: 0.79, 0.84, 0.82

So the other punctuation marks on the line, commas and colons, can also change, and are no help for finding the numbers you need.

You could use grep -o ... to extract only the words load average: onwards, and extract the correct word from that. But it would be far simpler to stop parsing the output of uptime entirely, and instead extract the load average from /proc/loadavg, if your OS has such a file:

$ cat /proc/loadavg
1.01 0.91 0.85 1/793 24545

If you only want the first number, ignoring decimals, you can do that with a single cut:

$ cut -d. -f1 /proc/loadavg
1
0

Your cut command is cutting out the 13th field, but you want the 14th field...

⇨  uptime |cut -d ' ' -f 13
average:

After that goes through your cut command, you are left with the 'a' character.

Try:

⇨  uptime |cut -d ' ' -f 14
0.18

Also note, your head -c 1 will cut the decimals off... I think you might be better off rounding up or something. Look at bc perhaps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.