Extracting Sensors Output into Sorted Array - bash

this question is the continuation of Extracting Ubuntu Sensors Command Using Scripts
Since the question was poorly written, I'm rewording the question in form of new question.
Basically I want to extract GPUs temperatures information using sensors command and scripts like gawk and bash.
Example of sensors output will be like this:
amdgpu-pci-0c00
Adapter: PCI adapter
fan1: 1972 RPM
temp1: +50.0°C (crit = +0.0°C, hyst = +0.0°C)
amdgpu-pci-0600
Adapter: PCI adapter
fan1: 1960 RPM
temp1: +47.0°C (crit = +0.0°C, hyst = +0.0°C)
amdgpu-pci-0200
Adapter: PCI adapter
fan1: 1967 RPM
temp1: +52.0°C (crit = +0.0°C, hyst = +0.0°C)
pch_skylake-virtual-0
Adapter: Virtual device
temp1: +33.0°C
amdgpu-pci-0900
Adapter: PCI adapter
fan1: 1893 RPM
temp1: +51.0°C (crit = +0.0°C, hyst = +0.0°C)
amdgpu-pci-0300
Adapter: PCI adapter
fan1: 1992 RPM
temp1: +53.0°C (crit = +0.0°C, hyst = +0.0°C)
coretemp-isa-0000
Adapter: ISA adapter
Package id 0: +24.0°C (high = +80.0°C, crit = +100.0°C)
Core 0: +23.0°C (high = +80.0°C, crit = +100.0°C)
Core 1: +21.0°C (high = +80.0°C, crit = +100.0°C)
The GPU temp information is labeled amdgpu-pci-"BUS_ID", so we don't care about other label scheme (skylake-virtual nor coretemp-isa). Things need to be done are:
Extracting the GPU temperatures info, for example amdgpu-pci-0c00
has 50 degree, and put in into an array.
The array index should be started with 0 and ascending in the order
of BUS ID.
If using the above data, the array assuming a is the name, would be:
a[0] = 52 ;amdgpu-pci-0200
a[1] = 53 ;amdgpu-pci-0300
a[2] = 47 ;amdgpu-pci-0600
a[3] = 51 ;amdgpu-pci-0900
a[4] = 50 ;amdgpu-pci-0c00
What I need for the output is an infinite loop that keep updating the array index with its value:
0 => 52
1 => 53
2 => 47
3 => 51
4 => 57
The new value should print over the old value so it won't trail. The update should have 1 second delay so the operator can easily evaluate the values.
The extracting and sorting could be done by GAwk, but I need it to be stored in an array in bash so that I can use it for other process.
regards

Reusing parts from your script and Ed Mortons answer I think this might work for you:
#!/bin/bash
while true
do
while read -r i temp ; do
echo -en "GPU $i temp is $temp \r "
sleep 1
done < <(
sensors | gawk '
!NF {name=""}
/amdgpu/ {
name=$1
}
/^temp1:/ && name {
temps[name]=gensub(/^[^0-9]*([0-9]+).*/,"\\1",1,$2);
}
END {
PROCINFO["sorted_in"] = "#ind_str_asc"
ctr=0;
for (i in temps) {
print ctr++,temps[i]
}
} '
)
done
Edit: if you need to store the values to an array (as stated in the question) for other purposes you can do it like this:
temps=( $( sensors | gawk '...' ) )
In this case change the print command in awk to only print temps[i]. My approach can be easily extended to include other values from the sensors output (like the gpu labels or fan speed).

Related

Using Sensors command for Lua to use in generating rings

I am trying to reverse engineer a conky/lua script to tailor fit my machine. The thing is, hwmon does not pickup the correct value. I resorted in using sensors to detect CPU temperature. I was able to successfully use it in lua to create an if/then/else function that changes colour depending on the temperature however, I could not get it to work with the "ring"
This is what I have currently:
local cpu_temp = io.popen("sensors -u | awk '/temp1_input:/ {print $2; exit}'"):read("*l")
local cpu0_temp = tonumber(cpu_temp:read('*a'))
settings_table = {
{
--1
name='hwmon',
arg='cpu0_temp',
max=110,
bg_colour=0x3b3b3b,
bg_alpha=0.8,
fg_colour=0x165cc4,
fg_alpha=0.8,
x=185, y=125,
radius=120,
thickness=4,
start_angle=0,
end_angle=240
},
}
function temp_watch()
warn_value=60
crit_value=80
local file= io.popen("sensors -u | awk '/temp1_input:/ {print $2; exit}'")
local temperature = tonumber(file:read('*a'))
if temperature<warn_value then
settings_table[1]['fg_colour']=normal
elseif temperature<crit_value then
settings_table[1]['fg_colour']=warn
else
settings_table[1]['fg_colour']=crit
end
file:close()
end
function conky_main()
temp_watch()
end
I am no expert in lua and I was patterning the first 2 lines on what I have learned and from this Question
What I get is this error:
conky: get_sysfs_info(): read from failed
conky: can't open '': No such file or directory
The original settings table looks like this:
settings_table = {
{
--1
name='hwmon',
arg='1 temp 1',
max=110,
bg_colour=0x3b3b3b,
bg_alpha=0.8,
fg_colour=0x165cc4,
fg_alpha=0.8,
x=185, y=125,
radius=120,
thickness=4,
start_angle=0,
end_angle=240
},
And it is stuck to 50 degrees Celsius.

Supercollider: Applying FX to a group seems to affect other groups

I have created separate groups on supercollider for each instrument so that I may apply FX, like echo, to the group and only affect one instrument rather than all instruments playing on that sc server.
On the node tree, the echo synthdef correctly appears in the required group (box) and the FX is applied to the instrument in that group, but ALSO incorrectly applying echo to the nodes in other groups on the same server.
What I have noticed is that it affects all higher number groups and not lower number groups. Applying FX (echo) to group 1 or group 2 also applies the same FX to groups 3,4,5,6,7,8, etc., but applying FX to group 8 does NOT seem to affect groups 1,2,3,4,5,6,& 7.
I have tested this on the following systems/versions....
supercollider version (1:3.10.0+repack-1ubuntu2) on ubuntu (Linux
Optiplex-3010 5.4.0-70-generic #78-Ubuntu SMP x86_64 x86_64 x86_64
GNU/Linux)
supercollider version (1:3.10.0+repack-1+rpi1) on Linux raspberrypi
4.19.75-v7l+ #1270 SMP armv7l GNU/Linux
supercollider version (1:3.8.0~repack-2) on Linux advent
5.0.0-32-generic #34~18.04.2-Ubuntu SMP 2019 i686 i686 i686 GNU/Linux
Is this a known bug? Can I make any manual changes to the supercollider code to resolve this? If not, then it will have to be a separate RPi4 for each instrument, underutilising each RPi and increasing project costs significantly.
Regards to all SCcoders,
Phil
Requested code:
(SynthDef(\echo,{|in, out, length = 1, fb = 0.6, sep = 1|
var input = In.ar(in, 2);
var feedback = LocalIn.ar(2);
var output = LeakDC.ar(feedback*fb + input);
LocalOut.ar(DelayC.ar(output, length, sep));
ReplaceOut.ar(out, output);
}).writeDefFile("/home/phil/Supercollider/syndef");)
I instigate the echo via OSC over tcp/ip, but essentially it would be called by:
/s_new s 'echo' i 1028 i 0 i 8 //in this case 1028 is the node for track 8
//and 8 is the SC group
and adjusted by:
/n_set i 1028 s 'fb' f 0.7
UPDATE: In answer to Fizz's comment about...
how I created groups, initially in the startup.scd file and then clear every time the live performance stops and create every time the live performance starts...
oscStream.Clear();
oscStream << osc::BeginBundleImmediate
<< osc::BeginMessage("/g_freeAll") << 1 << osc::EndMessage
<< osc::BeginMessage("/clearSched") << osc::EndMessage
<< osc::EndBundle;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
oscStream.Clear();
oscStream << osc::BeginMessage("/g_new") << 1 << 0 << 0
<< osc::EndMessage;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
oscStream.Clear();
oscStream << osc::BeginMessage("/g_new") << 2 << 0 << 0
<< osc::EndMessage;
transmitSocketMelody1.Send(oscStream.Data(),oscStream.Size());
which is the equivalent of...
s.sendMsg(\g_freeAll, 0);
s.sendMsg(\clearSched);
s.sendMsg(\g_new,1,0,0);
s.sendMsg(\g_new,2,0,0);
Order that I create synthdefs...
The echo synthdef (already shown above) is the first created via the supercollider startup.scd file.
Then the sound synthdefs are created in numerical order Piano1, Piano2, Piano3, etc... also via the supercollider startup.scd file.
s.sendMsg(\b_allocRead, 101,"piano-p-c4.wav"); //buffer 101
SynthDef.new("piano1", {|amp=1, freq|
var output,sig,sig2;
sig=PlayBuf.ar(2, 101, freq/523.25, doneAction:2);
sig=sig*amp;
sig = Splay.ar(sig);
Out.ar(0,sig!2);
}).store;
s.sendMsg(\b_allocRead, 111,"piano-p-c5.wav"); //buffer 111
SynthDef.new("piano2", {|amp=1, freq|
var sig;
sig=PlayBuf.ar(2, 111, freq/523.25, doneAction:2);
sig=sig*amp;
sig = Splay.ar(sig);
Out.ar(0,sig!2);
}).store;
The piano synthdefs are played live from the commands..
oscStream_melody1 << osc::BeginMessage("/s_new")
<< "piano1"
<< NextSCNode << 0 << 1
<< "freq" << OscFrequency[OSCOctave][OSCNote]
<< "amp" << Melody1Amplitude*Melody1Volume
<< osc::EndMessage
transmitSocketMelody1.Send(oscStream_melody1.Data(),oscStream_melody1.Size());
oscStream_melody2 << osc::BeginMessage("/s_new")
<< "piano2"
<< NextSCNode << 0 << 2
<< "freq" << OscFrequency[OSCOctave][OSCNote]
<< "amp" << Melody2Amplitude*Melody2Volume
<< osc::EndMessage;
transmitSocketMelody2.Send(oscStream_melody2.Data(),oscStream_melody2.Size());
which is the equivalent of...
s.sendMsg("/s_new","\piano1",1234, 0, 1,"freq",440,"amp", 0.8)
s.sendMsg("/s_new","\piano2",1235, 0, 2,"freq",880,"amp", 0.7)
echo is turned on, modified and off live thus...
s.sendMsg(\s_new,'echo',1001,0,X); //where X is the group to apply to
s.sendMsg(\n_set, 1001,'fb',0.5,'length',1,'sep',1);
s.sendMsg(\n_free, 1001);
but this turns on the echo for all groups with higher numbers, e.g group2, group3, group4 etc.
Whereas if reverb is set on group2 it affects group3, group4, etc but not group1.
Without seeing any code, this is hard to answer, but I wonder if you are using buses? Your instrument group should output to an echo bus and that bus should output to where you wish the sound to go next - another FX bus or to 0.
You'd want to draw a block diagram of your groups, connecting inputs and outputs. Keep in mind that any FX group can take ins from multiple places, but will only have one output. This means you may end up running the same FX synth more than once, for example, if you want echo on groups A and B, but then you want group B to go to a compressor afterwards.
Make sure to declare every bus, give it a good variable name and remember to pass it as an argument on synth creation.

How does fdisk utility use CHS addressing on SSDs?

In my free time I am working on a personal project for reading and writing all kinds of disk structures like MBR, GPT, EXT2/3/4, NTFS, etc. While working on the MBR part I noticed that the fdisk utility populates the CHS address fields of the MBR partition entries when formatting a device... even if the target device is an SSD or a normal file like a disk image. The lack of any actual cylinders and heads/platters in an SSD or file made me curious: What does fdisk write to those CHS address fields?
Well, after some testing (i.e. formatting a normal file multiple times with different start sectors for the first partition), I am fairly certain that fdisk actually writes CHS addresses into those fields. But how does fdisk determine the cylinder/head sizes for an SSD or for a normal file? I can't imagine the HDIO_REQ and HDIO_GETGEO ioctls working on normal files.
After some more testing (see below) I am confident that the CHS addresses produced by fdisk always satisfy sector % (255 * 63) == 63 * chs.head + (chs.sector - 1) and chs.cylinder == 0 with chs.head only taking values in [0,254] and chs.sector only taking values in [1,63], regardless of the underlying (device) file's size.
I used the following Python script to quickly convert from LBAs to fdisk-CHSs to generate test cases. Tested on normal files as well as device files with different sector sizes.
import ctypes, subprocess
class chs_struct (ctypes.LittleEndianStructure):
# Unused: No system modern enough to run Python uses CHS addressing
_pack_ = 1
_fields_ = [
( "head", ctypes.c_uint8 ),
( "sector", ctypes.c_uint8, 6 ),
( "cylinder_hi", ctypes.c_uint8, 2 ),
( "cylinder_lo", ctypes.c_uint8 )
]
def chs_of_sector (first_sector, filename):
"""
Formats the file pointed to by filename with a new MBR whose first and
only partition is a primary partition starting at the specified
first_sector. This function returns the corresponding CHS address the
fdisk utility calculated.
"""
with subprocess.Popen(
["fdisk", filename],
universal_newlines = True,
stdin = subprocess.PIPE,
stdout = subprocess.DEVNULL,
stderr = subprocess.DEVNULL
) as proc:
# +------------------------------------------- Create new MBR
# | +-------------------------------------- Create new partition
# | | +--------------------------------- Make it a primary partition...
# | | | +---------------------------- and make it the first partition...
# | | | | +--------------- starting at this sector
# | | | | | +----- Max out partition size
# | | | | | | + Write MBR to file
# v v v v vvvvvvvvvvvv v v
proc.communicate("\n".join(["o", "n", "p", "1", str(first_sector), "", "w"]))
with open(filename, "rb") as file:
file.seek(447) # Offset of the first partition entry's first sector CHS address
chs = chs_struct.from_buffer_copy(file.read(3))
return (chs.head, chs.cylinder_hi << 8 + chs.cylinder_lo, chs.sector)

Bash sed match line and return other line in a text file

I am trying to get object path for HFP-based telephony application. We have a script called list-modems which is able to list properties of object paths. I want to return the object path that has the Powered = b'1' line, but it is not certain where this line will be, I think this might be done with sed and regex, but I have no substantial experience with it. Therefore, I need some help. The file in question has some text like the following:
[ /hfp/org/bluez/hci0/dev_7C_46_85_3E_36_66 ]
Interfaces = b''
Lockdown = b'0'
Online = b'0'
Features = b''
Type = b'hfp'
Powered = b'0'
Name = b'MCO'
Emergency = b'0'
[ /hfp/org/bluez/hci0/dev_D0_FC_CC_12_6D_4D ]
Interfaces = b'org.ofono.VoiceCallManager org.ofono.CallVolume org.ofono.Handsfree org.ofono.NetworkRegistration '
Lockdown = b'0'
Online = b'1'
Serial = b'D0:FC:CC:12:6D:4D'
Features = b'net '
Type = b'hfp'
Powered = b'1'
Name = b"Ak\xc4\xb1n's J7 Prime"
Emergency = b'0'
[ org.ofono.VoiceCallManager ]
EmergencyNumbers = b'08 000 999 110 112 911 118 119 '
[ org.ofono.CallVolume ]
Muted = b'0'
SpeakerVolume = b'50'
MicrophoneVolume = b'50'
[ org.ofono.Handsfree ]
DistractedDrivingReduction = b'0'
Features = b'three-way-calling echo-canceling-and-noise-reduction voice-recognition release-all-held release-specified-active-call private-chat create-multiparty hf-indicators '
EchoCancelingNoiseReduction = b'1'
BatteryChargeLevel = b'3'
InbandRinging = b'1'
VoiceRecognition = b'0'
[ org.ofono.NetworkRegistration ]
Mode = b'auto-only'
Status = b'registered'
Strength = b'40'
Name = b'vodafone TR'
[ /hfp/org/bluez/hci0/dev_D8_5B_2A_5B_7B_E6 ]
Interfaces = b''
Lockdown = b'0'
Online = b'0'
Features = b''
Type = b'hfp'
Powered = b'0'
Name = b'Samsung Galaxy S7'
Emergency = b'0'
[ /hfp/org/bluez/hci0/dev_14_5A_05_AB_66_F4 ]
Interfaces = b''
Lockdown = b'0'
Online = b'0'
Features = b''
Type = b'hfp'
Powered = b'0'
Name = b"Ekrem iPhone'u"
Emergency = b'0'
[ /phonesim ]
Interfaces = b''
Lockdown = b'0'
Online = b'0'
Features = b''
Type = b'hardware'
Powered = b'0'
Emergency = b'0'
What I want to do is I want to return the object path i.e. /hfp/org/bluez/hci0/dev_D0_FC_CC_12_6D_4D if it has the property Powered = b'1'. Keep in mind that this file is randomly generated, i.e. places of each properties differ from one run to another run.
So far I have the following regex to match the object path:
./list-modems | grep -E '/hfp/org/bluez/hci[0-9]/dev_[0-9A-F]{2}_[0-9A-F]{2}_[0-9A-F]{2}_[0-9A-F]{2}_[0-9A-F]{2}_[0-9A-F]{2}'
Any help is greately appreciated how to further tackle this issue. Thanks in advance
EDIT:
Expected output for this example (since it has Powered = b'1'):
/hfp/org/bluez/hci0/dev_D0_FC_CC_12_6D_4D
You could use awk here:
awk '/^\[/{op=$0;next} /Powered.*b.1./{print op;exit}' ./list-modems
If the line starts with a [ then it grabs the line into variable op. If a line matches /Powered.*b.1./ then it prints whatever is in that variable and exits (assuming only one match in the file. If more matches are expected then just remove the ;exit).
You could also sub out the /^\[/ regex with your own to match the path, but given your file format I think that's overkill.
You can kill off those extra brackets too by running it through gensub as you print:
awk '/^\[/{op=$0;next} /Powered.*b.1./{print gensub(/\[\s|\s\]/,"","g", op);exit}' ./list-modems
In action on your sample data:
$ awk '/^\[/{op=$0;next} /Powered.*b.1./{print gensub(/\[\s|\s\]/,"","g", op);exit}' ./list-modems
/hfp/org/bluez/hci0/dev_D0_FC_CC_12_6D_4D
using grep and tr
./list-modems | grep -zPo '/hfp/org/bluez/hci\d/dev(_[0-9A-F]{2}){6}(?=((?!/hfp/org/bluez/hci)[\s\S])*Powered = b\0471\047)' | tr '\0' '\n'
and diverting recursive regex
./list-modems | grep -zPo '(/hfp/org/bluez/hci\d/dev(_[0-9A-F]{2}){6})(?=((?!(?1))[\s\S])*Powered = b\0471\047)' | tr '\0' '\n'

Toner levels using SNMP

I'm trying to get the toner levels from a Brother MCF-9465CDN using SNMP, in order to ultimately plot them in a graph using Munin. I'm not getting ink levels though.
Although I'm a bit new to SNMP, I assume what I'm trying should be possible.
$ snmpwalk -v 2c -c public a.b.c.d .1.3.6.1.2.1.43.11.1.1.6
iso.3.6.1.2.1.43.11.1.1.6.1.1 = STRING: "Black Toner Cartridge"
iso.3.6.1.2.1.43.11.1.1.6.1.2 = STRING: "Cyan Toner Cartridge"
iso.3.6.1.2.1.43.11.1.1.6.1.3 = STRING: "Magenta Toner Cartridge"
iso.3.6.1.2.1.43.11.1.1.6.1.4 = STRING: "Yellow Toner Cartridge"
iso.3.6.1.2.1.43.11.1.1.6.1.5 = STRING: "Waste Toner Box"
iso.3.6.1.2.1.43.11.1.1.6.1.6 = STRING: "Belt Unit"
iso.3.6.1.2.1.43.11.1.1.6.1.7 = STRING: "Drum Unit"
There are some other fields I'd like to monitor, such as the Drum and Belt pages left, on which I have more success: see the last two entries below.
Note that the Toner Cartridges are all reporting "-3", while I'd expect some kind of value I can use there.
$ snmpwalk -v 2c -c public a.b.c.d iso.3.6.1.2.1.43.11.1.1.9.1
iso.3.6.1.2.1.43.11.1.1.9.1.1 = INTEGER: -3
iso.3.6.1.2.1.43.11.1.1.9.1.2 = INTEGER: -3
iso.3.6.1.2.1.43.11.1.1.9.1.3 = INTEGER: -3
iso.3.6.1.2.1.43.11.1.1.9.1.4 = INTEGER: -3
iso.3.6.1.2.1.43.11.1.1.9.1.5 = INTEGER: -3
iso.3.6.1.2.1.43.11.1.1.9.1.6 = INTEGER: 48877
iso.3.6.1.2.1.43.11.1.1.9.1.7 = INTEGER: 15830
The Brother MFC is using the latest firmware version N1.10.
Using the MFC's web page on a.b.c.d I'm able to get an indication (using a bar) with the amount of toner capacity left.
It turns out that the "-3" return messages are expected.
My Brother MFC doesn't return the level of the toner using snmp, but just "full", "almost empty", "empty" or "absent".
See this question/answer on serverfault.

Resources