New version, man page. Features, bugs, fixes!

Bugs:
1. Color selector accepted '' as a value, which it would then write to config
file, creating errors since it's not an integer value.
2. Corrected distro id error for last fallback case, making the distro ID out
of the filename itself, that was missing the assignment to $distro.
3. mmcblk0 was showing up as an unmounted partition, due to failing to filter
mmcblk[0-9] in unmounted.

Fixes:
1. Added missing compositor kwin_wayland to compositor detections
2. For -M, on laptops, sometimes Type: would duplicate in Chassis: type: which
looks silly, so now it checks to make sure the two values are different before
using the Chassis: type: data.
3. -D disk vendor, added GALAX, fixed Toshiba, which sometimes occurs other than
start of disk id string, so now it checks the whole string. This seems particularly
common in nvme devices from Toshiba. This is the only vendor I have found that
puts the vendor string later in the device id string.
4. Added protection against unreadable but present /etc/issue. This was caused
by a now fixed bug in OpenSuSe, which symbolically linked to create /etc/issue
from /var/run/issue, but with 600 permissions, root read only, that is. Note that
this bug has since been fixed (now has the correct 644 permissions), but I figured
better safe than sorry in case anyone else decides that's a good idea in the future.
Now only sends to reader if readable.
5. Related to 4, made reader not exit on failure, now just prints error message and
keeps going.
6. Upped maximum distro string length to 60, from 50. AntiX for example was coming
in at 48, so I decided to add some safe room now that inxi does dynamic sizing, it
is not a big problem having very long distro id strings.

Enhancements:
1. Added basic /proc data parser to debugger. Can't get all the data or files because
it's simply too big, but grabs the basics.
2. Added vcgencmd for some ARM rasberry pi debugging.
3. ARM: add model if not found in /proc/cpuinfo, or if different.
4. Added Tdie cpu sensor type, this is coming soon in latest kernels, so catching
it early. Tdie will replace k10-temp sensor item temp1.
5. Added --admin extra data option, and first set of extra data, -C, which will
show CPU Errata (bugs), family, model-id, stepping (as hex (decimal) or hex if less
than or equal to 9), microcode (as hex).
6. Battery: added with -x option, if found, attached battery driven devices, like
wifi keyboard, mouse. If upower is present, will also try to show battery charge
percent for those devices. Note that -B only shows the Device-X items if -x is used,
and will not show anything in -F unless there is a system, not device, battery
present, or if -Fx is used and there is a Device battery detected.
Added upower to recommends.
7. Basic -Dxxx disk rotation speeds added. Requires udevadm. Not all spinning disks
show rotation speeds, and it depends on udevadm, so if no rotation found, it shows
nothing.
8. Added explicit Arco Linux and Antergos distro ID support. This requires more
checks, but in theory, both should now show Arco Linux or Antergos instead of default
'Arch Linux' as before, plus extra data if found, like version.
This commit is contained in:
Harald Hope 2018-06-04 17:24:53 -07:00
parent 2364629135
commit 1030b77d2e
3 changed files with 489 additions and 130 deletions

471
inxi
View file

@ -31,8 +31,8 @@ use POSIX qw(uname strftime ttyname);
## INXI INFO ## ## INXI INFO ##
my $self_name='inxi'; my $self_name='inxi';
my $self_version='3.0.10'; my $self_version='3.0.11';
my $self_date='2018-05-21'; my $self_date='2018-06-04';
my $self_patch='00'; my $self_patch='00';
## END INXI INFO ## ## END INXI INFO ##
@ -64,8 +64,8 @@ my (@dm_boot_disk,@dm_boot_optical,@glabel,@gpart,@labels,@lsblk,@partitions,
my @test = (0,0,0,0,0); my @test = (0,0,0,0,0);
## Booleans ## Booleans
my ($b_arm,$b_console_irc,$b_debug_gz,$b_display,$b_dmesg_boot_check,$b_dmi, my ($b_admin,$b_arm,$b_console_irc,$b_debug_gz,$b_display,$b_dmesg_boot_check,
$b_dmidecode_force,$b_fake_bsd,$b_fake_dboot,$b_fake_pciconf,$b_fake_sysctl, $b_dmi,$b_dmidecode_force,$b_fake_bsd,$b_fake_dboot,$b_fake_pciconf,$b_fake_sysctl,
$b_fake_usbdevs,$b_force_display,$b_gpudata,$b_irc,$b_log,$b_log_colors, $b_fake_usbdevs,$b_force_display,$b_gpudata,$b_irc,$b_log,$b_log_colors,
$b_log_full,$b_man,$b_mem,$b_pci,$b_root,$b_running_in_display,$b_sudo, $b_log_full,$b_man,$b_mem,$b_pci,$b_root,$b_running_in_display,$b_sudo,
$b_sysctl,$b_usb_check); $b_sysctl,$b_usb_check);
@ -474,6 +474,7 @@ sub set_user_paths {
# initialize function directly. # initialize function directly.
$self_path = $0; $self_path = $0;
$self_path =~ s/[^\/]+$//; $self_path =~ s/[^\/]+$//;
# print "0: $0 sp: $self_path\n";
if ( defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'} ){ if ( defined $ENV{'XDG_CONFIG_HOME'} && $ENV{'XDG_CONFIG_HOME'} ){
$user_config_dir=$ENV{'XDG_CONFIG_HOME'}; $user_config_dir=$ENV{'XDG_CONFIG_HOME'};
@ -869,7 +870,7 @@ sub get_selection {
@data = (); @data = ();
my $response = <STDIN>; my $response = <STDIN>;
chomp $response; chomp $response;
if ($response =~ /[^0-9]/ || $response > ($count + 3)){ if ($response =~ /([^0-9]|^$)/ || ( $response =~ /^[0-9]+$/ && $response > ($count + 3) )){
@data = ( @data = (
[0, '', '', "Error - Invalid Selection. You entered this: $response. Hit <ENTER> to continue."], [0, '', '', "Error - Invalid Selection. You entered this: $response. Hit <ENTER> to continue."],
[0, '', '', "$line1"], [0, '', '', "$line1"],
@ -1235,10 +1236,7 @@ package SystemDebugger;
#use POSIX qw(strftime); #use POSIX qw(strftime);
my $option = 'main'; my $option = 'main';
my $upload = ''; my ($data_dir,$debug_dir,$debug_gz,$parse_src,$upload) = ('','','','','');
my $data_dir = '';
my $debug_dir = '';
my $debug_gz = '';
my @content = (); my @content = ();
my $b_debug = 0; my $b_debug = 0;
my $b_delete_dir = 1; my $b_delete_dir = 1;
@ -1282,6 +1280,13 @@ sub run_debugger {
print "Skipping /sys data collection. /sys not present, or empty.\n"; print "Skipping /sys data collection. /sys not present, or empty.\n";
} }
print $line3; print $line3;
if ( -d '/proc' && main::count_dir_files('/proc') ){
proc_traverse_data();
}
else {
print "Skipping /proc data collection. /proc not present, or empty.\n";
}
print $line3;
} }
run_self(); run_self();
print $line3; print $line3;
@ -1662,7 +1667,10 @@ sub system_data {
['systemctl','list-units'], ['systemctl','list-units'],
['systemctl','list-units --type=target'], ['systemctl','list-units --type=target'],
['systemd-detect-virt',''], ['systemd-detect-virt',''],
['upower','-e'],
['uptime',''], ['uptime',''],
['vcgencmd','get_mem arm'],
['vcgencmd','get_mem gpu'],
); );
run_commands(\@cmds,'system'); run_commands(\@cmds,'system');
@files = main::globber('/dev/bus/usb/*/*'); @files = main::globber('/dev/bus/usb/*/*');
@ -1704,19 +1712,22 @@ sub system_files {
} }
sub copy_files { sub copy_files {
my ($files_ref, $type) = @_; my ($files_ref,$type,$alt_dir) = @_;
my ($absent,$error,$good,$name,$unreadable); my ($absent,$error,$good,$name,$unreadable);
my $directory = ($alt_dir) ? $alt_dir : $data_dir;
my $working = ($type ne 'proc') ? "$type-file-": '';
foreach (@$files_ref) { foreach (@$files_ref) {
$name = $_; $name = $_;
$name =~ s/^\///; $name =~ s/^\///;
$name =~ s/\//-/g; $name =~ s/\//~/g;
$name = "$data_dir/$type-file-$name"; $name = "$directory/$working$name";
$good = $name . '.txt'; $good = $name . '.txt';
$absent = $name . '-absent'; $absent = $name . '-absent';
$error = $name . '-error'; $error = $name . '-error';
$unreadable = $name . '-unreadable'; $unreadable = $name . '-unreadable';
if (-e $_ ) { # proc have already been tested for readable/exists
if (-r $_){ if ($type eq 'proc' || -e $_ ) {
if ($type eq 'proc' || -r $_){
copy($_,"$good") or main::toucher($error); copy($_,"$good") or main::toucher($error);
} }
else { else {
@ -1869,30 +1880,50 @@ sub sys_traverse_data {
print "Parsing /sys files...\n"; print "Parsing /sys files...\n";
# get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied # get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied
no warnings 'File::Find'; no warnings 'File::Find';
$parse_src = 'sys';
File::Find::find( \&wanted, "/sys"); File::Find::find( \&wanted, "/sys");
process_data(); process_sys_data();
@content = ();
}
sub proc_traverse_data {
print "Parsing /proc files...\n";
# get rid pointless error:Can't cd to (/sys/kernel/) debug: Permission denied
no warnings 'File::Find';
$parse_src = 'proc';
File::Find::find( \&wanted, "/proc");
process_proc_data();
@content = ();
} }
sub wanted { sub wanted {
return if -d; # not directory return if -d; # not directory
return unless -e; # Must exist return unless -e; # Must exist
return unless -r; # Must be readable
return unless -f; # Must be file return unless -f; # Must be file
# note: a new file in 4.11 /sys can hang this, it is /parameter/ then return unless -r; # Must be readable
# a few variables. Since inxi does not need to see that file, we will if ($parse_src eq 'sys'){
# not use it. Also do not need . files or __ starting files # note: a new file in 4.11 /sys can hang this, it is /parameter/ then
# print $File::Find::name . "\n"; # a few variables. Since inxi does not need to see that file, we will
# block maybe: cfgroup\/ # not use it. Also do not need . files or __ starting files
return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|parameters\/|debug\/)/; # print $File::Find::name . "\n";
# comment this one out if you experience hangs or if # block maybe: cfgroup\/
# we discover syntax of foreign language characters return if $File::Find::name =~ /\/(\.[a-z]|kernel\/|parameters\/|debug\/)/;
# Must be ascii like. This is questionable and might require further # comment this one out if you experience hangs or if
# investigation, it is removing some characters that we might want # we discover syntax of foreign language characters
return unless -T; # Must be ascii like. This is questionable and might require further
# investigation, it is removing some characters that we might want
return unless -T;
}
elsif ($parse_src eq 'proc') {
return if $File::Find::name =~ /^\/proc\/[0-9]+\//;
return if $File::Find::name =~ /^\/proc\/bus\/pci\//;
return if $File::Find::name =~ /^\/proc\/irq\//;
return if $File::Find::name =~ /(\/mb_groups|debug)$/;
return if $File::Find::name eq '/proc/kallsyms' || $File::Find::name eq '/proc/keys';
}
# print $File::Find::name . "\n"; # print $File::Find::name . "\n";
push (@content, $File::Find::name); push (@content, $File::Find::name);
return; return;
} }
sub process_data { sub process_sys_data {
my ($data,$fh,$result,$row,$sep); my ($data,$fh,$result,$row,$sep);
my $filename = "sys-data-parse.txt"; my $filename = "sys-data-parse.txt";
# no sorts, we want the order it comes in # no sorts, we want the order it comes in
@ -1915,6 +1946,16 @@ sub process_data {
close $fh; close $fh;
# print $fh "$result"; # print $fh "$result";
} }
sub process_proc_data {
my ($data,$fh,$result,$row,$sep);
my $proc_dir = "$data_dir/proc";
mkdir $proc_dir or main::error_handler('mkdir', "$proc_dir", "$!");
# @content = sort @content;
copy_files(\@content,'proc',$proc_dir);
# foreach (@content){
# print "$_\n";
# }
}
# args: 1 - path to file to be uploaded # args: 1 - path to file to be uploaded
# args: 2 - optional: alternate ftp upload url # args: 2 - optional: alternate ftp upload url
# NOTE: must be in format: ftp.site.com/incoming # NOTE: must be in format: ftp.site.com/incoming
@ -2134,8 +2175,10 @@ sub set_perl_downloader {
#### ------------------------------------------------------------------- #### -------------------------------------------------------------------
sub error_handler { sub error_handler {
eval $start if $b_log;
my ( $err, $one, $two) = @_; my ( $err, $one, $two) = @_;
my ($b_recommends,$b_help,$errno) = (0,0,0); my ($b_help,$b_recommends);
my ($b_exit,$errno) = (1,0);
my $message = do { my $message = do {
if ( $err eq 'empty' ) { 'empty value' } if ( $err eq 'empty' ) { 'empty value' }
## Basic rules ## Basic rules
@ -2169,7 +2212,7 @@ sub error_handler {
elsif ( $err eq 'mkdir' ) { elsif ( $err eq 'mkdir' ) {
$errno=44; "Error creating directory: $one \nError: $two" } $errno=44; "Error creating directory: $one \nError: $two" }
elsif ( $err eq 'open' ) { elsif ( $err eq 'open' ) {
$errno=45; "Error opening file: $one \nError: $two" } $errno=45; $b_exit=0; "Error opening file: $one \nError: $two" }
elsif ( $err eq 'open-dir' ) { elsif ( $err eq 'open-dir' ) {
$errno=46; "Error opening directory: $one \nError: $two" } $errno=46; "Error opening directory: $one \nError: $two" }
elsif ( $err eq 'output-file-bad' ) { elsif ( $err eq 'output-file-bad' ) {
@ -2210,7 +2253,8 @@ sub error_handler {
if ($b_recommends){ if ($b_recommends){
print_line("See --recommends for more information.\n"); print_line("See --recommends for more information.\n");
} }
exit 0; eval $end if $b_log;
exit 0 if $b_exit;
} }
sub error_defaults { sub error_defaults {
@ -2304,12 +2348,12 @@ sub check_items {
elsif ($type eq 'recommended system programs'){ elsif ($type eq 'recommended system programs'){
if ($bsd_type){ if ($bsd_type){
@data = qw(camcontrol dig dmidecode fdisk file glabel gpart ifconfig ipmi-sensors @data = qw(camcontrol dig dmidecode fdisk file glabel gpart ifconfig ipmi-sensors
ipmitool lsusb sudo smartctl sysctl tree uptime usbdevs); ipmitool lsusb sudo smartctl sysctl tree upower uptime usbdevs);
$info_os = 'info-bsd'; $info_os = 'info-bsd';
} }
else { else {
@data = qw(dig dmidecode fdisk file hddtemp ifconfig ip ipmitool ipmi-sensors @data = qw(dig dmidecode fdisk file hddtemp ifconfig ip ipmitool ipmi-sensors
lsblk lsusb modinfo runlevel sensors strings sudo tree uptime); lsblk lsusb modinfo runlevel sensors strings sudo tree upower uptime);
} }
$b_program = 1; $b_program = 1;
$item = 'Program'; $item = 'Program';
@ -2682,6 +2726,13 @@ sub item_data {
'pacman' => 'tree', 'pacman' => 'tree',
'rpm' => 'tree', 'rpm' => 'tree',
}), }),
'upower' => ({
'info' => '-sx attached device battery info',
'info-bsd' => '-sx attached device battery info',
'apt' => 'upower',
'pacman' => 'upower',
'rpm' => 'upower',
}),
'uptime' => ({ 'uptime' => ({
'info' => '-I uptime', 'info' => '-I uptime',
'info-bsd' => '-I uptime', 'info-bsd' => '-I uptime',
@ -3420,6 +3471,8 @@ sub get_options{
my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_recommends,$b_updater,$b_version, my ($b_downloader,$b_help,$b_no_man,$b_no_man_force,$b_recommends,$b_updater,$b_version,
$b_use_man,$self_download, $download_id); $b_use_man,$self_download, $download_id);
GetOptions ( GetOptions (
'admin' => sub {
$b_admin = 1;},
'A|audio' => sub { 'A|audio' => sub {
$show{'short'} = 0; $show{'short'} = 0;
$show{'audio'} = 1;}, $show{'audio'} = 1;},
@ -3987,7 +4040,7 @@ sub show_options {
['0', '', '', "Output Control Options:" ], ['0', '', '', "Output Control Options:" ],
['1', '-A', '--audio', "Audio/sound card(s), driver, sound server." ], ['1', '-A', '--audio', "Audio/sound card(s), driver, sound server." ],
['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ], ['1', '-b', '--basic', "Basic output, short form. Same as $self_name^-v^2." ],
['1', '-B', '--battery', "Battery info, including charge and condition, plus ['1', '-B', '--battery', "System battery info, including charge and condition, plus
extra info (if battery present)." ], extra info (if battery present)." ],
['1', '-c', '--color', "Set color scheme (0-42). Example:^$self_name^-c^11" ], ['1', '-c', '--color', "Set color scheme (0-42). Example:^$self_name^-c^11" ],
['1', '', '', "Color selectors let you set the config file value for the ['1', '', '', "Color selectors let you set the config file value for the
@ -4096,15 +4149,16 @@ sub show_options {
push @data, @rows; push @data, @rows;
} }
@rows = ( @rows = (
['1', '-x', '-extra', "Adds the following extra data (only works with ['1', '-x', '--extra', "Adds the following extra data (only works with
verbose or line output, not short form):" ], verbose or line output, not short form):" ],
['2', '-B', '', "Vendor/model, status (if available)." ], ['2', '-B', '', "Vendor/model, status (if available); attached devices
(e.g. wireless mouse, keyboard, if present)." ],
['2', '-C', '', "CPU $flags, Bogomips on CPU; CPU microarchitecture + ['2', '-C', '', "CPU $flags, Bogomips on CPU; CPU microarchitecture +
revision (if found)." ], revision (if found, or unless --admin, then shows as 'stepping')." ],
['2', '-d', '', "Extra optical drive features data; adds rev version to ['2', '-d', '', "Extra optical drive features data; adds rev version to
optical drive." ], optical drive." ],
['2', '-D', '', "HDD temp with disk data if you have hddtemp installed, ['2', '-D', '', "HDD temp with disk data if you have hddtemp installed,
if you are root, or if you have added to /etc/sudoers (sudo v. 1.7 or newer). if you are root, or if you have added to /etc/sudoers (sudo v. 1.7 or newer).
Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ], Example:^<username>^ALL^=^NOPASSWD:^/usr/sbin/hddtemp" ],
['2', '-G', '', "Direct rendering status (in X); Screen number GPU is ['2', '-G', '', "Direct rendering status (in X); Screen number GPU is
running on (Nvidia only)." ], running on (Nvidia only)." ],
@ -4164,7 +4218,8 @@ sub show_options {
['1', '-xxx', '--extra 3', "Show extra, extra, extra data (only works ['1', '-xxx', '--extra 3', "Show extra, extra, extra data (only works
with verbose or line output, not short form):" ], with verbose or line output, not short form):" ],
['2', '-B', '', "Chemistry, cycles, location (if available)." ], ['2', '-B', '', "Chemistry, cycles, location (if available)." ],
['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases." ], ['2', '-D', '', "Firmware rev. if available; partition scheme, in some cases; disk
rotation speed (if detected)." ],
['2', '-I', '', "For 'Shell:' adds ([su|sudo|login]) to shell name if present; ['2', '-I', '', "For 'Shell:' adds ([su|sudo|login]) to shell name if present;
for 'running in:' adds (SSH) if SSH session." ], for 'running in:' adds (SSH) if SSH session." ],
['2', '-m', '', "Width of memory bus, data and total (if present and greater ['2', '-m', '', "Width of memory bus, data and total (if present and greater
@ -4181,6 +4236,10 @@ sub show_options {
push @data, @rows; push @data, @rows;
} }
@rows = ( @rows = (
['1', '', '--admin', "Adds advanced sys admin data (only works with
verbose or line output, not short form):" ],
['2', '-C', '', "If available: CPU errata (bugs); family, model-id, stepping - format:
hex (decimal) if greater than 9, otherwise hex; microcode - format: hex." ],
['1', '-y', '--width', "Output line width max (integer >= 80). Overrides IRC/Terminal ['1', '-y', '--width', "Output line width max (integer >= 80). Overrides IRC/Terminal
settings or actual widths. Example:^inxi^-y^130" ], settings or actual widths. Example:^inxi^-y^130" ],
['1', '-z', '--filter', "Adds security filters for IP/MAC addresses, serial numbers, ['1', '-z', '--filter', "Adds security filters for IP/MAC addresses, serial numbers,
@ -4707,11 +4766,13 @@ sub clean_characters {
my ($data) = @_; my ($data) = @_;
# newline, pipe, brackets, + sign, with space, then clear doubled # newline, pipe, brackets, + sign, with space, then clear doubled
# spaces and then strip out trailing/leading spaces. # spaces and then strip out trailing/leading spaces.
$data =~ s/\n|\|\+|\[\s\]|\s\s+/ /g if $data; # etc/issue often has junk stuff like (\l) \n \l
$data =~ s/^\s+|\s+$//g if $data; return if ! $data;
$data =~ s/[:\47]|\\[a-z]|\n|,|\"|\*|\||\+|\[\s\]|n\/a|\s\s+/ /g;
$data =~ s/\(\)//;
$data =~ s/^\s+|\s+$//g;
return $data; return $data;
} }
sub cleaner { sub cleaner {
my ($item) = @_; my ($item) = @_;
return $item if !$item;# handle cases where it was 0 or '' return $item if !$item;# handle cases where it was 0 or ''
@ -4866,7 +4927,7 @@ sub row_defaults {
my %unfound = ( my %unfound = (
'arm-cpu-f' => 'Use -f option to see features', 'arm-cpu-f' => 'Use -f option to see features',
'arm-pci' => "PCI data type is not supported on ARM systems.", 'arm-pci' => "PCI data type is not supported on ARM systems.",
'battery-data' => "No battery data found. Is one present?", 'battery-data' => "No system battery data found. Is one present?",
'battery-data-sys' => "No /sys data found. Old system?", 'battery-data-sys' => "No /sys data found. Old system?",
'cpu-model-null' => "Model N/A", 'cpu-model-null' => "Model N/A",
'darwin-feature' => "Feature not supported iu Darwin/OSX.", 'darwin-feature' => "Feature not supported iu Darwin/OSX.",
@ -5624,10 +5685,10 @@ sub sound_server_data {
## BatteryData ## BatteryData
{ {
package BatteryData; package BatteryData;
my (@upower_items,$b_upower,$upower);
sub get { sub get {
eval $start if $b_log; eval $start if $b_log;
my (@rows,$key1,%battery,$val1); my (@rows,%battery,$key1,$val1);
my $num = 0; my $num = 0;
if ($bsd_type || $b_dmidecode_force){ if ($bsd_type || $b_dmidecode_force){
my $ref = $alerts{'dmidecode'}; my $ref = $alerts{'dmidecode'};
@ -5671,6 +5732,7 @@ sub get {
@rows = ({main::key($num++,$key1) => $val1,}); @rows = ({main::key($num++,$key1) => $val1,});
} }
} }
(@upower_items,$b_upower,$upower) = undef;
eval $end if $b_log; eval $end if $b_log;
return @rows; return @rows;
} }
@ -5697,20 +5759,22 @@ sub get {
# 17 location # 17 location
sub create_output { sub create_output {
eval $start if $b_log; eval $start if $b_log;
my (%battery,@data,@rows) = @_; my (%battery) = @_;
my ($key); my ($key,@data,@rows);
my $num = 0; my $num = 0;
my $j = 0; my $j = 0;
# print Data::Dumper::Dumper \%battery;
foreach $key (sort keys %battery){ foreach $key (sort keys %battery){
$num = 0; $num = 0;
my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','',''); my ($charge,$condition,$model,$serial,$status,$volts) = ('','','','','','');
my ($chemistry,$cycles,$location) = ('','',''); my ($chemistry,$cycles,$location) = ('','','');
next if !$battery{$key}{'purpose'} || $battery{$key}{'purpose'} ne 'primary';
# $battery{$key}{''}; # $battery{$key}{''};
# we need to handle cases where charge or energy full is 0 # we need to handle cases where charge or energy full is 0
$charge = ($battery{$key}{'energy_now'} || $battery{$key}{'energy_now'} eq 0) ? "$battery{$key}{'energy_now'} Wh" : 'N/A'; $charge = (defined $battery{$key}{'energy_now'} && $battery{$key}{'energy_now'} ne '') ? "$battery{$key}{'energy_now'} Wh" : 'N/A';
if ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full_design'}){ if ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full_design'}){
$battery{$key}{'energy_full_design'} ||= 'N/A'; $battery{$key}{'energy_full_design'} ||= 'N/A';
$battery{$key}{'energy_full'}= ($battery{$key}{'energy_full'} || $battery{$key}{'energy_full'} eq 0) ? $battery{$key}{'energy_full'} : 'N/A'; $battery{$key}{'energy_full'}= (defined $battery{$key}{'energy_full'} && $battery{$key}{'energy_full'} ne '') ? $battery{$key}{'energy_full'} : 'N/A';
$condition = "$battery{$key}{'energy_full'}/$battery{$key}{'energy_full_design'} Wh"; $condition = "$battery{$key}{'energy_full'}/$battery{$key}{'energy_full_design'} Wh";
if ($battery{$key}{'of_orig'}){ if ($battery{$key}{'of_orig'}){
$condition .= " ($battery{$key}{'of_orig'}%)"; $condition .= " ($battery{$key}{'of_orig'}%)";
@ -5768,6 +5832,57 @@ sub create_output {
} }
} }
} }
$battery{$key} = undef;
}
# print Data::Dumper::Dumper \%battery;
# now if there are any devices left, print them out, excluding Mains
if ($extra > 0){
$upower = main::check_program('upower');
foreach $key (sort keys %battery){
$num = 0;
next if !defined $battery{$key} || $battery{$key}{'purpose'} eq 'mains';
my ($charge,$model,$serial,$percent,$status,$vendor) = ('','','','','','');
my (%upower_data);
$j = scalar @rows;
%upower_data = upower_data($key) if $upower;
if ($upower_data{'percent'}){
$charge = $upower_data{'percent'};
}
elsif ($battery{$key}{'capacity_level'} && lc($battery{$key}{'capacity_level'}) ne 'unknown'){
$charge = $battery{$key}{'capacity_level'};
}
else {
$charge = 'N/A';
}
$model = $battery{$key}{'model_name'} if $battery{$key}{'model_name'};
$status = ($battery{$key}{'status'} && lc($battery{$key}{'status'}) ne 'unknown') ? $battery{$key}{'status'}: 'N/A' ;
$vendor = $battery{$key}{'manufacturer'} if $battery{$key}{'manufacturer'};
if ($vendor || $model){
if ($vendor && $model){
$model = "$vendor $model";
}
elsif ($vendor){
$model = $vendor;
}
}
else {
$model = 'N/A';
}
@data = ({
main::key($num++,'Device') => $key,
main::key($num++,'model') => $model,
},);
@rows = (@rows,@data);
if ($extra > 1){
$serial = main::apply_filter($battery{$key}{'serial_number'});
$rows[$j]{main::key($num++,'serial')} = $serial;
}
$rows[$j]{main::key($num++,'charge')} = $charge;
if ($extra > 2 && $upower_data{'rechargeable'}){
$rows[$j]{main::key($num++,'rechargeable')} = $upower_data{'rechargeable'};
}
$rows[$j]{main::key($num++,'status')} = $status;
}
} }
eval $end if $b_log; eval $end if $b_log;
return @rows; return @rows;
@ -5778,10 +5893,9 @@ sub battery_data_sys {
eval $start if $b_log; eval $start if $b_log;
my ($b_ma,%battery,$file,$id,$item,$path,$value); my ($b_ma,%battery,$file,$id,$item,$path,$value);
my $num = 0; my $num = 0;
# NOTE: known ids: BAT[0-9] CMB[0-9] my @batteries = main::globber("/sys/class/power_supply/*");
my @batteries = main::globber("/sys/class/power_supply/[BC][AM][TB]*/");
# note: there is no 'location' file, but dmidecode has it # note: there is no 'location' file, but dmidecode has it
# 'type' is generic, like: Battery # 'type' is generic, like: Battery, Mains
# capacity_level is a string, like: Normal # capacity_level is a string, like: Normal
my @items = qw(alarm capacity capacity_level charge_full charge_full_design charge_now my @items = qw(alarm capacity capacity_level charge_full charge_full_design charge_now
cycle_count energy_full energy_full_design energy_now location manufacturer model_name cycle_count energy_full energy_full_design energy_now location manufacturer model_name
@ -5789,11 +5903,20 @@ sub battery_data_sys {
foreach $item (@batteries){ foreach $item (@batteries){
$b_ma = 0; $b_ma = 0;
$id = $item; $id = $item;
$id =~ s%/sys/class/power_supply/|\/$%%g; $id =~ s%/sys/class/power_supply/%%g;
my $purpose = ($id =~ /^(BAT|CMB).*$/) ? 'primary': 'device';
# don't create arrays of device data if it's not going to show
next if $extra == 0 && $purpose ne 'primary';
$battery{$id} = ({}); $battery{$id} = ({});
# NOTE: known ids: BAT[0-9] CMB[0-9]
$battery{$id}{'purpose'} = $purpose;
foreach $file (@items){ foreach $file (@items){
$path = "$item$file"; $path = "$item/$file";
$value = (-f $path) ? (main::reader($path))[0]: ''; $value = (-f $path) ? (main::reader($path))[0]: '';
# mains
if ($file eq 'type' && $value && lc($value) ne 'battery' ){
$battery{$id}{'purpose'} = 'mains';
}
if ($value){ if ($value){
if ($file eq 'voltage_min_design'){ if ($file eq 'voltage_min_design'){
$value = sprintf("%.1f", $value/1000000); $value = sprintf("%.1f", $value/1000000);
@ -5887,6 +6010,7 @@ sub battery_data_dmi {
$id = "BAT$i"; $id = "BAT$i";
$i++; $i++;
$battery{$id} = ({}); $battery{$id} = ({});
$battery{$id}{'purpose'} = 'primary';
# skip first three row, we don't need that data # skip first three row, we don't need that data
splice @ref, 0, 3 if @ref; splice @ref, 0, 3 if @ref;
foreach my $item (@ref){ foreach my $item (@ref){
@ -5923,6 +6047,35 @@ sub battery_data_dmi {
eval $end if $b_log; eval $end if $b_log;
return %battery; return %battery;
} }
sub upower_data {
my ($id) = @_;
eval $start if $b_log;
my (%data);
if (!$b_upower && $upower){
@upower_items = main::grabber("$upower -e",'','strip');
$b_upower = 1;
}
if ($upower && @upower_items){
foreach (@upower_items){
if ($_ =~ /$id/){
my @working = main::grabber("$upower -i $_",'','strip');
foreach my $row (@working){
my @temp = split /\s*:\s*/, $row;
if ($temp[0] eq 'percentage'){
$data{'percent'} = $temp[1];
}
elsif ($temp[0] eq 'rechargeable'){
$data{'rechargeable'} = $temp[1];
}
}
last;
}
}
}
eval $end if $b_log;
return %data;
}
} }
## CpuData ## CpuData
@ -5993,10 +6146,18 @@ sub create_output_full {
if ($extra > 0){ if ($extra > 0){
$cpu{'arch'} ||= 'N/A'; $cpu{'arch'} ||= 'N/A';
$rows[$j]{main::key($num++,'arch')} = $cpu{'arch'}; $rows[$j]{main::key($num++,'arch')} = $cpu{'arch'};
if ( $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){ if ( !$b_admin && $cpu{'arch'} ne 'N/A' && $cpu{'rev'} ){
$rows[$j]{main::key($num++,'rev')} = $cpu{'rev'}; $rows[$j]{main::key($num++,'rev')} = $cpu{'rev'};
} }
} }
if ($b_admin){
$rows[$j]{main::key($num++,'family')} = hex_and_decimal($cpu{'family'});
$rows[$j]{main::key($num++,'model-id')} = hex_and_decimal($cpu{'model_id'});
$rows[$j]{main::key($num++,'stepping')} = hex_and_decimal($cpu{'rev'});
$cpu{'microcode'} ||= 'N/A';
$rows[$j]{main::key($num++,'microcode')} = $cpu{'microcode'};
}
$properties{'l2-cache'} ||= 'N/A'; $properties{'l2-cache'} ||= 'N/A';
$rows[$j]{main::key($num++,'L2 cache')} = $properties{'l2-cache'} if (!$b_arm || ($b_arm && $properties{'l2-cache'} ne 'N/A')); $rows[$j]{main::key($num++,'L2 cache')} = $properties{'l2-cache'} if (!$b_arm || ($b_arm && $properties{'l2-cache'} ne 'N/A'));
if ($extra > 0 && !$show{'cpu-flag'}){ if ($extra > 0 && !$show{'cpu-flag'}){
@ -6056,6 +6217,15 @@ sub create_output_full {
},); },);
@rows = (@rows,@data); @rows = (@rows,@data);
} }
if ($b_admin && $cpu{'bugs'}){
my @bugs = split /\s+/, $cpu{'bugs'};
@bugs = sort(@bugs);
my $bug = join ' ', @bugs;
@data = ({
main::key($num++,'Errata') => $bug,
},);
@rows = (@rows,@data);
}
eval $end if $b_log; eval $end if $b_log;
return @rows; return @rows;
} }
@ -6256,7 +6426,7 @@ sub data_cpuinfo {
} }
} }
elsif (!$cpu{'rev'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision' )){ elsif (!$cpu{'rev'} && ($line[0] eq 'stepping' || $line[0] eq 'cpu revision' )){
$cpu{'rev'} = $line[1]; $cpu{'rev'} = uc(sprintf("%x", $line[1]));
} }
# this is hex so uc for cpu arch id # this is hex so uc for cpu arch id
elsif (!$cpu{'model_id'} && $line[0] eq 'model' ){ elsif (!$cpu{'model_id'} && $line[0] eq 'model' ){
@ -6351,6 +6521,21 @@ sub data_cpuinfo {
$cpu{'bogomips'} += $line[1] if $line[1] > 50; $cpu{'bogomips'} += $line[1] if $line[1] > 50;
} }
} }
if ($b_admin ){
if ( !$cpu{'bugs'} && $line[0] eq 'bugs'){
$cpu{'bugs'} = $line[1];
}
# unlike family and model id, microcode appears to be hex already
if ( !$cpu{'microcode'} && $line[0] eq 'microcode'){
if ($line[1] =~ /0x/){
$cpu{'microcode'} = uc($line[1]);
$cpu{'microcode'} =~ s/^0X//;
}
else {
$cpu{'microcode'} = uc(sprintf("%x", $line[1]));
}
}
}
} }
$cpu{'phys'} = scalar @phys_cpus; $cpu{'phys'} = scalar @phys_cpus;
$cpu{'dies'} = $die_id++; # count starts at 0, all cpus have 1 die at least $cpu{'dies'} = $die_id++; # count starts at 0, all cpus have 1 die at least
@ -7119,6 +7304,16 @@ sub cpu_cleaner {
$cpu =~ s/^\s+|\s+$//g; $cpu =~ s/^\s+|\s+$//g;
return $cpu; return $cpu;
} }
sub hex_and_decimal {
my ($data) = @_;
if ($data){
$data .= ' (' . hex($data) . ')' if hex($data) ne $data;
}
else {
$data = 'N/A';
}
return $data;
}
} }
## DiskData ## DiskData
@ -7256,6 +7451,9 @@ sub create_output {
$rows[$j]{main::key($num++,'speed')} = $row{'speed'}; $rows[$j]{main::key($num++,'speed')} = $row{'speed'};
$rows[$j]{main::key($num++,'lanes')} = $row{'lanes'} if $row{'lanes'}; $rows[$j]{main::key($num++,'lanes')} = $row{'lanes'} if $row{'lanes'};
} }
if ($extra > 2 && $row{'rotation'}){
$rows[$j]{main::key($num++,'rotation')} = $row{'rotation'};
}
if ($extra > 1){ if ($extra > 1){
my $serial = main::apply_filter($row{'serial'}); my $serial = main::apply_filter($row{'serial'});
$rows[$j]{main::key($num++,'serial')} = $serial; $rows[$j]{main::key($num++,'serial')} = $serial;
@ -7407,9 +7605,10 @@ sub proc_data_advanced {
($block_type,$firmware,$model,$partition_scheme, ($block_type,$firmware,$model,$partition_scheme,
$serial,$vendor,$working_path) = ('','','','','','',''); $serial,$vendor,$working_path) = ('','','','','','','');
if ($extra > 2){ if ($extra > 2){
@data = partition_scheme($pt_cmd,$drives[$i]{'id'}); @data = advanced_disk_data($pt_cmd,$drives[$i]{'id'});
$pt_cmd = $data[0]; $pt_cmd = $data[0];
$drives[$i]{'partition-table'} = uc($data[1]) if $data[1]; $drives[$i]{'partition-table'} = uc($data[1]) if $data[1];
$drives[$i]{'rotation'} = "$data[2] rpm" if $data[2];
} }
#print "$drives[$i]{'id'}\n"; #print "$drives[$i]{'id'}\n";
@disk_data = disk_data_by_id("/dev/$drives[$i]{'id'}"); @disk_data = disk_data_by_id("/dev/$drives[$i]{'id'}");
@ -7654,7 +7853,7 @@ sub peripheral_data {
eval $end if $b_log; eval $end if $b_log;
return $type; return $type;
} }
sub partition_scheme { sub advanced_disk_data {
eval $start if $b_log; eval $start if $b_log;
my ($set_cmd,$id) = @_; my ($set_cmd,$id) = @_;
my ($cmd,$pt,$program,@data,@return); my ($cmd,$pt,$program,@data,@return);
@ -7665,15 +7864,13 @@ sub partition_scheme {
# runs as user, but is SLOW: udisksctl info -b /dev/sda # runs as user, but is SLOW: udisksctl info -b /dev/sda
# line: org.freedesktop.UDisks2.PartitionTable: # line: org.freedesktop.UDisks2.PartitionTable:
# Type: dos # Type: dos
if (!$b_root){ if ($program = main::check_program('udevadm')){
if ($program = main::check_program('udevadm')){ $return[0] = "$program info -q property -n ";
$return[0] = "$program info -q property -n ";
}
} }
if (!$return[0] && $b_root && -e "/lib/udev/udisks-part-id") { elsif ($b_root && -e "/lib/udev/udisks-part-id") {
$return[0] = "/lib/udev/udisks-part-id /dev/"; $return[0] = "/lib/udev/udisks-part-id /dev/";
} }
elsif (!$return[0] && $b_root && ($program = main::check_program('fdisk'))) { elsif ($b_root && ($program = main::check_program('fdisk'))) {
$return[0] = "$program -l /dev/"; $return[0] = "$program -l /dev/";
} }
if (!$return[0]) { if (!$return[0]) {
@ -7700,9 +7897,19 @@ sub partition_scheme {
$return[1] = 'dos' if !$return[1]; $return[1] = 'dos' if !$return[1];
} }
else { else {
$return[1] = main::awk(\@data,'^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)',2,'='); foreach (@data){
if ( /^(UDISKS_PARTITION_TABLE_SCHEME|ID_PART_TABLE_TYPE)/ ){
my @working = split /=/, $_;
$return[1] = $working[1];
}
elsif (/^ID_ATA_ROTATION_RATE_RPM/){
my @working = split /=/, $_;
$return[2] = $working[1];
}
last if $return[1] && $return[2];
}
} }
$return[1] = 'mbr' if $return[1] && $return[1] eq 'dos'; $return[1] = 'mbr' if $return[1] && lc($return[1]) eq 'dos';
} }
eval $end if $b_log; eval $end if $b_log;
return @return; return @return;
@ -7807,7 +8014,8 @@ sub device_vendor {
['^PNY','^PNY\s','PNY','','^PNY'], ['^PNY','^PNY\s','PNY','','^PNY'],
['^(SanDisk|SDS[S]?[DQ]|SL([0-9]+)G|AFGCE)','^SanDisk','SanDisk',''], ['^(SanDisk|SDS[S]?[DQ]|SL([0-9]+)G|AFGCE)','^SanDisk','SanDisk',''],
# note: get rid of: M[DGK] becasue mushkin starts with MK # note: get rid of: M[DGK] becasue mushkin starts with MK
['^([S]?TOS|THN)','^[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_ # note: seen: KXG50ZNV512G NVMe TOSHIBA 512GB | THNSN51T02DUK NVMe TOSHIBA 1024GB
['(^[S]?TOS|^THN|TOSHIBA)','[S]?TOSHIBA','Toshiba',''], # scsi-STOSHIBA_STOR.E_EDITION_
## These go last because they are short and could lead to false ID, or are unlikely ## ## These go last because they are short and could lead to false ID, or are unlikely ##
['^Android','^Android','Android',''], ['^Android','^Android','Android',''],
# must come before AP|Apacer # must come before AP|Apacer
@ -7815,6 +8023,7 @@ sub device_vendor {
['^(AP|Apacer)','^Apacer','Apacer',''], ['^(AP|Apacer)','^Apacer','Apacer',''],
['^BUFFALO','^BUFFALO','Buffalo',''], ['^BUFFALO','^BUFFALO','Buffalo',''],
['^EXCELSTOR','^EXCELSTOR( TECHNOLOGY)?','Excelstor',''], ['^EXCELSTOR','^EXCELSTOR( TECHNOLOGY)?','Excelstor',''],
['^GALAX\b','^GALAX','GALAX',''],
['^Generic','^Generic','Generic',''], ['^Generic','^Generic','Generic',''],
['^GOODRAM','^GOODRAM','GOODRAM',''], ['^GOODRAM','^GOODRAM','GOODRAM',''],
# supertalent also has FM: |FM # supertalent also has FM: |FM
@ -7870,6 +8079,7 @@ sub device_vendor {
$vendor = $row[2]; $vendor = $row[2];
$model =~ s/$row[1]//i if $row[1] && lc($model) ne lc($row[1]); $model =~ s/$row[1]//i if $row[1] && lc($model) ne lc($row[1]);
$model =~ s/^[\s\-_]+|[\s\-_]+$//g; $model =~ s/^[\s\-_]+|[\s\-_]+$//g;
$model =~ s/\s\s/ /g;
@data = ($vendor,$model); @data = ($vendor,$model);
last; last;
} }
@ -8536,6 +8746,9 @@ sub display_compositor {
if (main::check_program('mutter') && (grep {/mutter/} @ps_cmd ) ) { if (main::check_program('mutter') && (grep {/mutter/} @ps_cmd ) ) {
$compositor = 'mutter'; $compositor = 'mutter';
} }
elsif (main::check_program('kwin_wayland') && (grep {/\bkwin_wayland\b/} @ps_cmd ) ) {
$compositor = 'kwin_wayland';
}
elsif (main::check_program('kwin') && (grep {/\bkwin\b/} @ps_cmd ) ) { elsif (main::check_program('kwin') && (grep {/\bkwin\b/} @ps_cmd ) ) {
$compositor = 'kwin'; $compositor = 'kwin';
} }
@ -8725,7 +8938,8 @@ sub create_output {
if ($data{'chassis_vendor'} ne $data{'sys_vendor'} ){ if ($data{'chassis_vendor'} ne $data{'sys_vendor'} ){
$chassis_vendor = $data{'chassis_vendor'}; $chassis_vendor = $data{'chassis_vendor'};
} }
if ($data{'chassis_type'} ){ # dmidecode can have these be the same
if ($data{'chassis_type'} && $data{'device'} ne $data{'chassis_type'} ){
$chassis_type = $data{'chassis_type'}; $chassis_type = $data{'chassis_type'};
} }
if ($data{'chassis_version'}){ if ($data{'chassis_version'}){
@ -8797,11 +9011,18 @@ sub create_output_arm {
my $num = 0; my $num = 0;
my $j = 0; my $j = 0;
#print Data::Dumper::Dumper \%arm_machine; #print Data::Dumper::Dumper \%arm_machine;
if ($arm_machine{'device'}){ # this is sketchy, /proc/device-tree/model may be similar to Hardware value from /proc/cpuinfo
my $device = main::cleaner( $arm_machine{'device'} ); # raspi: Hardware : BCM2835 model: Raspberry Pi Model B Rev 2
$device ||= 'N/A'; if ($arm_machine{'device'} || $arm_machine{'model'}){
$rows[$j]{main::key($num++,'Type')} = 'ARM Device'; $rows[$j]{main::key($num++,'Type')} = 'ARM Device';
$rows[$j]{main::key($num++,'System')} = $device; my $system = 'System';
if (defined $arm_machine{'model'}){
$rows[$j]{main::key($num++,'System')} = $arm_machine{'model'};
$system = 'v';
}
my $device = $arm_machine{'device'};
$device ||= 'N/A';
$rows[$j]{main::key($num++,$system)} = $device;
} }
# we're going to print N/A for 0000 values sine the item was there. # we're going to print N/A for 0000 values sine the item was there.
if ($arm_machine{'firmware'}){ if ($arm_machine{'firmware'}){
@ -8892,7 +9113,7 @@ sub machine_data_arm {
foreach (@data){ foreach (@data){
if (/^Hardware/i){ if (/^Hardware/i){
@temp = split /\s*:\s*/, $_; @temp = split /\s*:\s*/, $_;
$arm_machine{'device'} = $temp[1]; $arm_machine{'device'} = main::cleaner($temp[1]);
} }
elsif (/^Revision/i){ elsif (/^Revision/i){
@temp = split /\s*:\s*/, $_; @temp = split /\s*:\s*/, $_;
@ -8904,6 +9125,19 @@ sub machine_data_arm {
} }
} }
} }
if (-f '/proc/device-tree/model'){
my $model = (main::reader('/proc/device-tree/model'))[0];
main::log_data('data',"device-tree-model: $model") if $b_log;
if ( $model ){
$model = main::dmi_cleaner($model);
my (@result) = ();
@result = split(/\s+/, $arm_machine{'device'}) if $arm_machine{'device'};
if ( !$arm_machine{'device'} ||
(scalar(@result) == 1 && $model !~ /$arm_machine{'device'}/) ){
$arm_machine{'model'} = $model;
}
}
}
#print Data::Dumper::Dumper \%arm_machine; #print Data::Dumper::Dumper \%arm_machine;
eval $end if $b_log; eval $end if $b_log;
return %arm_machine; return %arm_machine;
@ -12871,9 +13105,14 @@ sub sensors_data {
# which is the maximum CPU temperature reported as critical temperature by coretemp" # which is the maximum CPU temperature reported as critical temperature by coretemp"
# NOTE: I've seen an inexplicable case where: CPU:52.0°C fails to match with [\s°] but # NOTE: I've seen an inexplicable case where: CPU:52.0°C fails to match with [\s°] but
# does match with: [\s°]*. I can't account for this, but that's why the * is there # does match with: [\s°]*. I can't account for this, but that's why the * is there
elsif (!$sensors{'cpu-temp'} && $_ =~ /^CPU.*:([0-9\.]+)[\s°]*(C|F)/i) { # Tdie is a new k10temp-pci syntax for cpu die temp
$sensors{'cpu-temp'} = $1; elsif ($_ =~ /^(CPU.*|Tdie.*):([0-9\.]+)[\s°]*(C|F)/i) {
$working_unit = $2; $temp_working = $2;
$working_unit = $3;
if ( !$sensors{'cpu-temp'} ||
( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'cpu-temp'} ) ) {
$sensors{'cpu-temp'} = $temp_working;
}
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
} }
elsif ($_ =~ /^PECI\sAgent\s0.*:([0-9\.]+)[\s°]*(C|F)/i) { elsif ($_ =~ /^PECI\sAgent\s0.*:([0-9\.]+)[\s°]*(C|F)/i) {
@ -12890,13 +13129,13 @@ sub sensors_data {
$sensors{'sodimm-temp'} = $1; $sensors{'sodimm-temp'} = $1;
$working_unit = $2; $working_unit = $2;
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
} }
# for temp1/2 only use temp1/2 if they are null or greater than the last ones # for temp1/2 only use temp1/2 if they are null or greater than the last ones
elsif ($_ =~ /^temp1:([0-9\.]+)[\s°]*(C|F)/i) { elsif ($_ =~ /^temp1:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1; $temp_working = $1;
$working_unit = $2; $working_unit = $2;
if ( !$sensors{'temp1'} || ( defined $temp_working && $temp_working > 0 ) ) { if ( !$sensors{'temp1'} ||
( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp1'} ) ) {
$sensors{'temp1'} = $temp_working; $sensors{'temp1'} = $temp_working;
} }
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@ -12904,7 +13143,8 @@ sub sensors_data {
elsif ($_ =~ /^temp2:([0-9\.]+)[\s°]*(C|F)/i) { elsif ($_ =~ /^temp2:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1; $temp_working = $1;
$working_unit = $2; $working_unit = $2;
if ( !$sensors{'temp2'} || ( defined $temp_working && $temp_working > 0 ) ) { if ( !$sensors{'temp2'} ||
( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp2'} ) ) {
$sensors{'temp2'} = $temp_working; $sensors{'temp2'} = $temp_working;
} }
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@ -12913,7 +13153,8 @@ sub sensors_data {
elsif ($_ =~ /^temp3:([0-9\.]+)[\s°]*(C|F)/i) { elsif ($_ =~ /^temp3:([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $1; $temp_working = $1;
$working_unit = $2; $working_unit = $2;
if ( !$sensors{'temp3'} || ( defined $temp_working && $temp_working > 0 ) ) { if ( !$sensors{'temp3'} ||
( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'temp3'} ) ) {
$sensors{'temp3'} = $temp_working; $sensors{'temp3'} = $temp_working;
} }
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@ -12923,7 +13164,8 @@ sub sensors_data {
elsif ($_ =~ /^(core0|core 0|Physical id 0)(.*):([0-9\.]+)[\s°]*(C|F)/i) { elsif ($_ =~ /^(core0|core 0|Physical id 0)(.*):([0-9\.]+)[\s°]*(C|F)/i) {
$temp_working = $3; $temp_working = $3;
$working_unit = $4; $working_unit = $4;
if ( !$sensors{'core-0-temp'} || ( defined $temp_working && $temp_working > 0 ) ) { if ( !$sensors{'core-0-temp'} ||
( defined $temp_working && $temp_working > 0 && $temp_working > $sensors{'core-0-temp'} ) ) {
$sensors{'core-0-temp'} = $temp_working; $sensors{'core-0-temp'} = $temp_working;
} }
$sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit; $sensors{'temp-unit'} = set_temp_unit($sensors{'temp-unit'},$working_unit) if $working_unit;
@ -13580,9 +13822,10 @@ sub unmounted_data {
# lvm might have dm-1 type syntax # lvm might have dm-1 type syntax
# need to exclude loop type file systems, squashfs for example # need to exclude loop type file systems, squashfs for example
# NOTE: nvme needs special treatment because the main device is: nvme0n1 # NOTE: nvme needs special treatment because the main device is: nvme0n1
if ( $working[-1] !~ /^nvme[0-9]+n[0-9]+$/ && # note: $working[2] != 1 is wrong, it's not related
$working[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && $working[2] != 1 && if ( $working[-1] !~ /^(nvme[0-9]+n|mmcblk)[0-9]+$/ &&
$working[-1] !~ /loop/ && !(grep {$working[-1] =~ /$_/} @mounted)){ $working[-1] =~ /[a-z][0-9]+$|dm-[0-9]+$/ && $working[-1] !~ /loop/ &&
!(grep {$working[-1] =~ /$_/} @mounted)){
%part = PartitionData::check_lsblk($working[-1],0) if (@lsblk && $working[-1]); %part = PartitionData::check_lsblk($working[-1],0) if (@lsblk && $working[-1]);
if (%part){ if (%part){
$fs = $part{'fs'}; $fs = $part{'fs'};
@ -14993,7 +15236,7 @@ sub get_bsd_os {
sub get_linux_distro { sub get_linux_distro {
eval $start if $b_log; eval $start if $b_log;
my ($distro_file) = (''); my ($distro_file) = ('');
my ($b_osr,@working); my ($b_antergos,$b_osr,@working);
my @derived = qw(antix-version aptosid-version kanotix-version knoppix-version my @derived = qw(antix-version aptosid-version kanotix-version knoppix-version
mandrake-release manjaro-release mx-version pardus-release porteus-version sabayon-release mandrake-release manjaro-release mx-version pardus-release porteus-version sabayon-release
siduction-version sidux-version slitaz-release solusos-release turbolinux-release siduction-version sidux-version slitaz-release solusos-release turbolinux-release
@ -15011,18 +15254,29 @@ sub get_linux_distro {
# uses this method # uses this method
my @distro_files = glob('/etc/*[-_]{[rR]elease,[vV]ersion}*'); my @distro_files = glob('/etc/*[-_]{[rR]elease,[vV]ersion}*');
my $lsb_release = '/etc/lsb-release'; my $lsb_release = '/etc/lsb-release';
my $issue = '/etc/issue'; my ($etc_issue,$issue) = ('','/etc/issue');
my $os_release = '/etc/os-release'; my $os_release = '/etc/os-release';
my $b_os_release = ( -f $os_release ) ? 1 : 0; my $b_issue = 1 if -f $issue;
my $b_lsb = ( -f $lsb_release ) ? 1 : 0; my $b_os_release = 1 if -f $os_release;
my $b_lsb = 1 if -f $lsb_release;
# note: OpenSuse Tumbleweed 2018-05 has made /etc/issue created by sym link to /run/issue
# and then made that resulting file 700 permissions, which is obviously a mistake
$etc_issue = (main::reader($issue))[0] if $b_issue && -r $issue;
# debian issue can end with weird escapes like \n \l
# antergos: Antergos Linux \r (\l)
if ($etc_issue){
$etc_issue = main::clean_characters($etc_issue);
$b_antergos = 1 if $etc_issue =~ /antergos/i;
}
main::log_data('dump','@distro_files',\@distro_files) if $b_log; main::log_data('dump','@distro_files',\@distro_files) if $b_log;
if ( scalar @distro_files == 1 ){ if ( scalar @distro_files == 1 ){
$distro_file = $distro_files[0]; $distro_file = $distro_files[0];
} }
elsif (scalar @distro_files > 1) { elsif (scalar @distro_files > 1) {
# special case, to force manjaro which also has arch-release # special case, to force manjaro/antergos which also have arch-release
# manjaro should use lsb, which has the full info, arch uses os release # manjaro should use lsb, which has the full info, arch uses os release
if (grep {/manjaro/} @distro_files){ # antergos should use /etc/issue
if ($b_antergos || grep {/manjaro/} @distro_files){
@distro_files = grep {!/arch-release/} @distro_files; @distro_files = grep {!/arch-release/} @distro_files;
} }
my $distro_files_s = join "|", @distro_files; my $distro_files_s = join "|", @distro_files;
@ -15076,29 +15330,26 @@ sub get_linux_distro {
# not use a variable type format # not use a variable type format
@working = main::reader($distro_file); @working = main::reader($distro_file);
$distro = main::awk(\@working,'suse'); $distro = main::awk(\@working,'suse');
$distro = main::clean_characters($distro) if $distro;
} }
else { else {
$distro = (main::reader($distro_file))[0]; $distro = (main::reader($distro_file))[0];
} }
$distro = main::clean_characters($distro) if $distro;
} }
# otherwise try the default debian/ubuntu /etc/issue file # otherwise try the default debian/ubuntu /etc/issue file
elsif (-f $issue){ elsif ($b_issue){
@working = main::reader($issue); my $b_mint = ( $etc_issue && $etc_issue =~ /mint/i ) ? 1 : 0;
my $b_mint = scalar (grep {/mint/i} @working);
# os-release/lsb gives more manageable and accurate output than issue, # os-release/lsb gives more manageable and accurate output than issue,
# but mint should use issue for now. # but mint should use issue for now. Antergos uses arch os-release, but issue shows them
if ($b_os_release && !$b_mint){ if ($b_os_release && !$b_mint && !$b_antergos){
$distro = get_os_release(); $distro = get_os_release();
$b_osr = 1; $b_osr = 1;
} }
elsif ($b_lsb && !$b_mint){ elsif ($b_lsb && !$b_mint && !$b_antergos){
$distro = get_lsb_release(); $distro = get_lsb_release();
} }
else { elsif ($etc_issue) {
# debian issue can end with weird escapes like \n \l $distro = $etc_issue;
@working = main::reader($issue);
$distro = (map {s/\\[a-z]|,|\*|\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @working)[0] if @working;
# this handles an arch bug where /etc/arch-release is empty and /etc/issue # this handles an arch bug where /etc/arch-release is empty and /etc/issue
# is corrupted only older arch installs that have not been updated should # is corrupted only older arch installs that have not been updated should
# have this fallback required, new ones use os-release # have this fallback required, new ones use os-release
@ -15109,8 +15360,8 @@ sub get_linux_distro {
} }
# a final check. If a long value, before assigning the debugger output, if os-release # a final check. If a long value, before assigning the debugger output, if os-release
# exists then let's use that if it wasn't tried already. Maybe that will be better. # exists then let's use that if it wasn't tried already. Maybe that will be better.
# not handling the corrupt data, maybe later if needed # not handling the corrupt data, maybe later if needed. 10 + distro: (8) + string
if ($distro && length($distro) > 50 ){ if ($distro && length($distro) > 60 ){
if (!$b_osr && $b_os_release){ if (!$b_osr && $b_os_release){
$distro = get_os_release(); $distro = get_os_release();
} }
@ -15132,7 +15383,8 @@ sub get_linux_distro {
# the file name itself to set the distro value. Why say unknown if we have # the file name itself to set the distro value. Why say unknown if we have
# a pretty good idea, after all? # a pretty good idea, after all?
if ($distro_file){ if ($distro_file){
$distro_file =~ s/[-_]|release|version//g; $distro_file =~ s/\/etc\/|[-_]|release|version//g;
$distro = $distro_file;
} }
} }
## finally, if all else has failed, give up ## finally, if all else has failed, give up
@ -15140,6 +15392,7 @@ sub get_linux_distro {
eval $end if $b_log; eval $end if $b_log;
return $distro; return $distro;
} }
sub get_lsb_release { sub get_lsb_release {
eval $start if $b_log; eval $start if $b_log;
my ($distro,$id,$release,$codename,$description) = ('','','','',''); my ($distro,$id,$release,$codename,$description) = ('','','','','');
@ -15186,8 +15439,8 @@ sub get_lsb_release {
} }
sub get_os_release { sub get_os_release {
eval $start if $b_log; eval $start if $b_log;
my ($pretty_name,$name,$version_name,$version_id, my ($pretty_name,$lc_name,$name,$version_name,$version_id,
$distro_name,$distro) = ('','','','','',''); $distro_name,$distro) = ('','','','','','','');
my @content = main::reader('/etc/os-release'); my @content = main::reader('/etc/os-release');
main::log_data('dump','@content',\@content) if $b_log; main::log_data('dump','@content',\@content) if $b_log;
@content = map {s/\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @content if @content; @content = map {s/\\||\"|[:\47]|^\s+|\s+$|n\/a//ig; $_} @content if @content;
@ -15200,6 +15453,7 @@ sub get_os_release {
} }
if ($working[0] eq 'NAME' && $working[1]){ if ($working[0] eq 'NAME' && $working[1]){
$name = $working[1]; $name = $working[1];
$lc_name = lc($name);
} }
if ($working[0] eq 'VERSION' && $working[1]){ if ($working[0] eq 'VERSION' && $working[1]){
$version_name = $working[1]; $version_name = $working[1];
@ -15209,18 +15463,19 @@ sub get_os_release {
} }
} }
# NOTE: tumbleweed has pretty name but pretty name does not have version id # NOTE: tumbleweed has pretty name but pretty name does not have version id
if ($pretty_name && $pretty_name !~ /tumbleweed/i){ # arco shows only the release name, like kirk, in pretty name
if ($pretty_name && ($pretty_name !~ /tumbleweed/i && $lc_name ne 'arcolinux') ){
$distro = $pretty_name; $distro = $pretty_name;
} }
elsif ($name){ elsif ($name){
$distro = $name; $distro = $name;
$distro = 'Arco Linux' if $lc_name eq 'arcolinux';
if ($version_name){ if ($version_name){
$distro .= ' ' . $version_name; $distro .= ' ' . $version_name;
} }
elsif ($version_id){ elsif ($version_id){
$distro .= ' ' . $version_id; $distro .= ' ' . $version_id;
} }
} }
eval $end if $b_log; eval $end if $b_log;
return $distro; return $distro;

82
inxi.1
View file

@ -1,4 +1,4 @@
.TH INXI 1 "2018\-05\-21" inxi "inxi manual" .TH INXI 1 "2018\-06\-04" inxi "inxi manual"
.SH NAME .SH NAME
inxi \- Command line system information script for console and IRC inxi \- Command line system information script for console and IRC
.SH SYNOPSIS .SH SYNOPSIS
@ -10,10 +10,9 @@ inxi \- Command line system information script for console and IRC
[\fBNUMBER\fR]] [\fB\-v NUMBER\fR] [\fB\-W LOCATION\fR] [\fBNUMBER\fR]] [\fB\-v NUMBER\fR] [\fB\-W LOCATION\fR]
[\fB\-\-weather\-unit\fR {\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR}] [\fB\-y WIDTH\fR] [\fB\-\-weather\-unit\fR {\fBm\fR|\fBi\fR|\fBmi\fR|\fBim\fR}] [\fB\-y WIDTH\fR]
\fBinxi\fR [\fB\-\-recommends\fR] \fR[\fB\-\-slots\fR] \fR[\fB\-\-usb\fR] \fBinxi\fR [\fB\-\-recommends\fR] \fR[\fB\-\-slots\fR] \fR[\fB\-\-usb\fR]
\fBinxi\fB \-x\fR|\fB\-xx\fR|\fB\-xxx\fR \fB\-OPTION(s) \fR \fBinxi\fB [\-x\fR|\fB\-xx\fR|\fB\-xxx\fR|\-\-admin] \fB\-OPTION(s) \fR
All options have long form variants \- see below for these and more advanced options. All options have long form variants \- see below for these and more advanced options.
@ -63,10 +62,11 @@ Show Audio/sound card(s) information, including card driver.
Show basic output, short form. Same as: \fBinxi \-v 2\fR Show basic output, short form. Same as: \fBinxi \-v 2\fR
.TP .TP
.B \-B\fR,\fB \-\-battery\fR .B \-B\fR,\fB \-\-battery\fR
Show Battery data, charge, condition, plus extra information (if battery present). Show system battery (\fBID\-x\fR) data, charge, condition, plus extra information
Uses \fB/sys\fR or, for BSDs without systctl battery data, \fBdmidecode\fR. (if battery present). Uses \fB/sys\fR or, for BSDs without systctl battery data,
\fBdmidecode\fR does not have very much information, and none about current battery \fBdmidecode\fR. \fBdmidecode\fR does not have very much information, and none
state/charge/voltage. Supports multiple batteries when using \fB/sys\fR data. about current battery state/charge/voltage. Supports multiple batteries when
using \fB/sys\fR data.
Note that for \fBcharge\fR, the output shows the current charge, as well as its Note that for \fBcharge\fR, the output shows the current charge, as well as its
value as a percentage of the available capacity, which can be less than the original design value as a percentage of the available capacity, which can be less than the original design
@ -80,6 +80,9 @@ capacity, and then this figure as a percentage of original capacity available in
\fBcondition: 22.2/36.4 Wh (61%)\fR \fBcondition: 22.2/36.4 Wh (61%)\fR
With \fB\-x\fR shows attached \fBDevice\-x\fR information (mouse, keyboard, etc.)
if they are battery powered.
.TP .TP
.B \-c\fR,\fB \-\-color\fR \fR[\fB0\fR\-\fB42\fR] .B \-c\fR,\fB \-\-color\fR \fR[\fB0\fR\-\fB42\fR]
Set color scheme. If no scheme number is supplied, 0 is assumed. Set color scheme. If no scheme number is supplied, 0 is assumed.
@ -478,8 +481,15 @@ device.
.B \-x \-B\fR .B \-x \-B\fR
\- Adds vendor/model, battery status (if battery present). \- Adds vendor/model, battery status (if battery present).
.TP .TP
.B \-x \-B\fR
\- Adds attached battery powered peripherals (\fBDevice\-[number]:\fR) if
detected (keyboard, mouse, etc.).
.TP
.B \-x \-C\fR .B \-x \-C\fR
\- Adds bogomips on CPU (if available); CPU Flags (short list). \- Adds bogomips on CPU (if available)
.TP
.B \-x \-C\fR
\- Adds CPU Flags (short list).
.TP .TP
.B \-x \-C\fR .B \-x \-C\fR
\- Adds CPU microarchitecture + revision (e.g. Sandy Bridge, K8, ARMv8, P6, \- Adds CPU microarchitecture + revision (e.g. Sandy Bridge, K8, ARMv8, P6,
@ -689,11 +699,21 @@ always shows \fB0\fR. There's nothing that can be done about this glitch, the
data is simply not available as of 2018\-04\-03), location (only available from data is simply not available as of 2018\-04\-03), location (only available from
\fBdmidecode\fR derived output). \fBdmidecode\fR derived output).
.TP .TP
.B \-xxx \-B\fR
\- Adds attached device \fBrechargeable: [yes|no]\fR information.
.TP
.B \-xxx \-D\fR .B \-xxx \-D\fR
\- Adds disk firmware revision number (if available). \- Adds disk firmware revision number (if available).
.TP .TP
.B \-xxx \-D\fR .B \-xxx \-D\fR
\- Adds disk partition scheme (in some but not all cases), e.g. \fBscheme: GPT\fR \- Adds disk partition scheme (in most cases), e.g. \fBscheme: GPT\fR. Currently not
able to detect all schemes, but handles the most common, e.g. \fBGPT\fR or \fBMBR\fR.
.TP
.B \-xxx \-D\fR
\- Adds disk rotation speed (in some but not all cases), e.g. \fBrotation: 7200 rpm\fR.
Only appears if detected (SSD drives do not have rotation speeds, for example). If none
found, nothing shows. Not all disks report this speed, so even if they are spinnning,
no data will show.
.TP .TP
.B \-xxx \-I\fR .B \-xxx \-I\fR
\- For \fBShell:\fR adds \fB(su|sudo|login)\fR to shell name if present. \- For \fBShell:\fR adds \fB(su|sudo|login)\fR to shell name if present.
@ -737,6 +757,22 @@ If none found, shows nothing.
.B \-xxx \-w\fR,\fB \-W\fR .B \-xxx \-w\fR,\fB \-W\fR
\- Adds location (city state country), altitude, weather observation time. \- Adds location (city state country), altitude, weather observation time.
.SH ADMIN EXTRA DATA OPTIONS
These options are triggered with \fB\-\-admin\fR. Admin options are advanced output options,
and are more technical, and mostly of interest to system administrators or other machine admins.
The \fB\-\-admin\fR option only has to be used once, and will trigger the following features.
.TP
.B \-\-admin \-C\fR
\- Adds CPU family, model\-id, and stepping (replaces \fBrev\fR of \fB\-Cx\fR).
Format is \fBhexadecimal (decimal)\fR if greater than 9, otherwise \fBhexadecimal\fR.
.TP
.B \-\-admin \-C\fR
\- Adds CPU microcode. Format is \fBhexadecimal\fR.
.TP
.B \-\-admin \-C\fR
\- Adds CPU Errata (bugs) as known by your current kernel.
.SH ADVANCED OPTIONS .SH ADVANCED OPTIONS
.TP .TP
@ -871,17 +907,13 @@ Overrides default internal value and user configuration value:
.B \-\-debug 11\fR .B \-\-debug 11\fR
\- Full file/system info logging. \- Full file/system info logging.
.TP
.B \-\-debug [20\-22]\fR
Debugger output generator.
.TP .TP
.B \-\-debug 20\fR .B \-\-debug 20\fR
Creates a tar.gz file of system data and collects the inxi output Creates a tar.gz file of system data and collects the inxi output
in a file. in a file.
* tree traversal data file read from \fB/sys\fR, and other system * tree traversal data file(s) read from \fB/proc\fR and \fB/sys\fR, and
data. other system data.
* xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc. * xorg conf and log data, xrandr, xprop, xdpyinfo, glxinfo etc.
@ -978,7 +1010,8 @@ See the documentation page for more complete information on how to set
these up, and for a complete list of options: these up, and for a complete list of options:
.I https://smxi.org/docs/inxi\-configuration.htm .I https://smxi.org/docs/inxi\-configuration.htm
.TP
.B Basic Options
Here's a brief overview of the basic options you are likely to want to use: Here's a brief overview of the basic options you are likely to want to use:
\fBCOLS_MAX_CONSOLE\fR The max display column width on terminal. \fBCOLS_MAX_CONSOLE\fR The max display column width on terminal.
@ -1014,6 +1047,8 @@ above configuration page on smxi.org for full info.
\fBWEATHER_UNIT\fR Values: [\fBc\fR|\fBf\fR|\fBcf\fR|\fBfc\fR]. Same as \fB\-\-weather\-unit\fR. \fBWEATHER_UNIT\fR Values: [\fBc\fR|\fBf\fR|\fBcf\fR|\fBfc\fR]. Same as \fB\-\-weather\-unit\fR.
.TP
.B Color Options
It's best to use the \fB\-c [94\-99]\fR color selector tool to set the following values It's best to use the \fB\-c [94\-99]\fR color selector tool to set the following values
because it will correctly update the configuration file and remove any invalid because it will correctly update the configuration file and remove any invalid
or conflicting items, but if you prefer to create your own configuration files, or conflicting items, but if you prefer to create your own configuration files,
@ -1035,19 +1070,24 @@ here are the options. All take the integer value from the options available in
.SH BUGS .SH BUGS
Please report bugs using the following resources. Please report bugs using the following resources.
You may be asked to run the inxi debugger tool which will upload a data dump of You may be asked to run the inxi debugger tool (see \fB\-\-debug 21/22\fR), which will
system files for use in debugging inxi. These data dumps are very important since upload a data dump of system files for use in debugging inxi. These data dumps are
they provide us with all the real system data inxi uses to parse out its report. very important since they provide us with all the real system data inxi uses to parse
out its report.
.TP .TP
inxi main website/source/wiki, file an issue report: .B Issue Report
File an issue report:
.I https://github.com/smxi/inxi/issues .I https://github.com/smxi/inxi/issues
.TP .TP
post on inxi developer forums: .B Developer Forums
Post on inxi developer forums:
.I https://techpatterns.com/forums/forum\-32.html .I https://techpatterns.com/forums/forum\-32.html
.TP .TP
.B IRC irc.oftc.net#smxi
You can also visit You can also visit
.I irc.oftc.net .I irc.oftc.net
\fRchannel:\fI #smxi\fR to post issues. \fRchannel:\fI #smxi\fR to post issues.
.SH HOMEPAGE .SH HOMEPAGE
.I https://github.com/smxi/inxi .I https://github.com/smxi/inxi
.I https://smxi.org/ .I https://smxi.org/

View file

@ -1,3 +1,67 @@
=====================================================================================
Version: 3.0.11
Patch Version: 00
Script Date: 2018-06-04
-----------------------------------
Changes:
-----------------------------------
New version, man page. Features, bugs, fixes!
Bugs:
1. Color selector accepted '' as a value, which it would then write to config
file, creating errors since it's not an integer value.
2. Corrected distro id error for last fallback case, making the distro ID out
of the filename itself, that was missing the assignment to $distro.
3. mmcblk0 was showing up as an unmounted partition, due to failing to filter
mmcblk[0-9] in unmounted.
Fixes:
1. Added missing compositor kwin_wayland to compositor detections
2. For -M, on laptops, sometimes Type: would duplicate in Chassis: type: which
looks silly, so now it checks to make sure the two values are different before
using the Chassis: type: data.
3. -D disk vendor, added GALAX, fixed Toshiba, which sometimes occurs other than
start of disk id string, so now it checks the whole string. This seems particularly
common in nvme devices from Toshiba. This is the only vendor I have found that
puts the vendor string later in the device id string.
4. Added protection against unreadable but present /etc/issue. This was caused
by a now fixed bug in OpenSuSe, which symbolically linked to create /etc/issue
from /var/run/issue, but with 600 permissions, root read only, that is. Note that
this bug has since been fixed (now has the correct 644 permissions), but I figured
better safe than sorry in case anyone else decides that's a good idea in the future.
Now only sends to reader if readable.
5. Related to 4, made reader not exit on failure, now just prints error message and
keeps going.
6. Upped maximum distro string length to 60, from 50. AntiX for example was coming
in at 48, so I decided to add some safe room now that inxi does dynamic sizing, it
is not a big problem having very long distro id strings.
Enhancements:
1. Added basic /proc data parser to debugger. Can't get all the data or files because
it's simply too big, but grabs the basics.
2. Added vcgencmd for some ARM rasberry pi debugging.
3. ARM: add model if not found in /proc/cpuinfo, or if different.
4. Added Tdie cpu sensor type, this is coming soon in latest kernels, so catching
it early. Tdie will replace k10-temp sensor item temp1.
5. Added --admin extra data option, and first set of extra data, -C, which will
show CPU Errata (bugs), family, model-id, stepping (as hex (decimal) or hex if less
than or equal to 9), microcode (as hex).
6. Battery: added with -x option, if found, attached battery driven devices, like
wifi keyboard, mouse. If upower is present, will also try to show battery charge
percent for those devices. Note that -B only shows the Device-X items if -x is used,
and will not show anything in -F unless there is a system, not device, battery
present, or if -Fx is used and there is a Device battery detected.
Added upower to recommends.
7. Basic -Dxxx disk rotation speeds added. Requires udevadm. Not all spinning disks
show rotation speeds, and it depends on udevadm, so if no rotation found, it shows
nothing.
8. Added explicit Arco Linux and Antergos distro ID support. This requires more
checks, but in theory, both should now show Arco Linux or Antergos instead of default
'Arch Linux' as before, plus extra data if found, like version.
-----------------------------------
-- Harald Hope - Mon, 04 Jun 2018 16:48:53 -0700
===================================================================================== =====================================================================================
Version: 3.0.10 Version: 3.0.10
Patch Version: 00 Patch Version: 00
@ -5,7 +69,7 @@ Script Date: 2018-05-21
----------------------------------- -----------------------------------
Changes: Changes:
----------------------------------- -----------------------------------
New version, new tarball. New version, new man page.
This version is very peaceful, no big changes, just a few fixes and small new This version is very peaceful, no big changes, just a few fixes and small new
features added. features added.