diff --git a/fanspeed/fanspeed b/fanspeed/fanspeed new file mode 100755 index 0000000..63b2b85 --- /dev/null +++ b/fanspeed/fanspeed @@ -0,0 +1,259 @@ +#!/bin/bash + +: <<'_EOS' +=pod +=cut + +=head1 NAME + +fanspeed - set fanspeed using IPMI + +=head1 SYNOPSIS + +B IC + +B I + +B bios + + +=head1 DESCRIPTION + +B will set the fanspeed using IPMI. + + +=head1 OPTIONS + +=over 9 + +=item IC + +Run fans at 40% unless temperature goes above I. When that +happens: Let BIOS control the fan for 30 seconds. + + +=item I + +Run fans at I percent. + + +=item bios + +Let BIOS control the fans. + + +=back + + +=head1 EXAMPLES + +=head2 EXAMPLE: + +Run fans at 40% unless temperature is above 60C. When temperature is +above 60C, let BIOS control fans. + + fanspeed 60C + + +=head2 EXAMPLE: Run fans at 50% + + fanspeed 50 + + +=head2 EXAMPLE: Let BIOS control fans + + fanspeed bios + + +=head1 REPORTING BUGS + +Report bugs: https://gitlab.com/ole.tange/tangetools/-/issues + + +=head1 AUTHOR + +Copyright (C) 2020 Ole Tange, http://ole.tange.dk and Free +Software Foundation, Inc. + + +=head1 LICENSE + +Copyright (C) 2013 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +at your option any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +=head2 Documentation license I + +Permission is granted to copy, distribute and/or modify this documentation +under the terms of the GNU Free Documentation License, Version 1.3 or +any later version published by the Free Software Foundation; with no +Invariant Sections, with no Front-Cover Texts, and with no Back-Cover +Texts. A copy of the license is included in the file fdl.txt. + +=head2 Documentation license II + +You are free: + +=over 9 + +=item B + +to copy, distribute and transmit the work + +=item B + +to adapt the work + +=back + +Under the following conditions: + +=over 9 + +=item B + +You must attribute the work in the manner specified by the author or +licensor (but not in any way that suggests that they endorse you or +your use of the work). + +=item B + +If you alter, transform, or build upon this work, you may distribute +the resulting work only under the same, similar or a compatible +license. + +=back + +With the understanding that: + +=over 9 + +=item B + +Any of the above conditions can be waived if you get permission from +the copyright holder. + +=item B + +Where the work or any of its elements is in the public domain under +applicable law, that status is in no way affected by the license. + +=item B + +In no way are any of the following rights affected by the license: + +=over 2 + +=item * + +Your fair dealing or fair use rights, or other applicable +copyright exceptions and limitations; + +=item * + +The author's moral rights; + +=item * + +Rights other persons may have either in the work itself or in +how the work is used, such as publicity or privacy rights. + +=back + +=back + +=over 9 + +=item B + +For any reuse or distribution, you must make clear to others the +license terms of this work. + +=back + +A copy of the full license is included in the file as cc-by-sa.txt. + +=head1 DEPENDENCIES + +B uses IPMItool, and sensors. + + +=head1 SEE ALSO + +B(1), jq(1), and B(1). + +=cut +_EOS + +setfanspeed() { + # 0..100 = manual control X% + # bios = BIOS control + ipmi() { + DRAC_USER=${DRAC_USER:-root} + DRAC_PASSWD=${DRAC_PASSWD:-calvin} + DRAC_HOST=${DRAC_HOST:-drac} + echo -n $(ipmitool -I lanplus -H "$DRAC_HOST" -U "$DRAC_USER" -P "$DRAC_PASSWD" raw "$@") + } + if [ "$1" == "bios" ] ; then + # Let BIOS run the fan + ipmi 0x30 0x30 0x01 0x01 + else + # Manual control + ipmi 0x30 0x30 0x01 0x00 + # Set speed 0..100 + ipmi 0x30 0x30 0x02 0xff "$@" + fi +} + +fanspeedthreshold() { + # fanspeedthreshold deg + # Turn on BIOS control when temperature reaches deg degrees + sensors -j | + jq -r '[.[]["temp1"]["temp1_input"]] | + if max < '$1' then 40 else "bios" end'; +} + +runthreshold() { + # runthreshold degrees + while true; do + printf " "$(sensors -j | + jq '[.[]["temp1"]["temp1_input"]] | max') + speed=$(fanspeedthreshold $@) + setfanspeed $speed + if [ $speed == "bios" ] ; then + # Do not change away from bios in less than 30 secs + sleep 30 + fi + sleep 1 + done +} + + +_fanspeed() { + # BIOS = 60 C => 40 + # 0 C => 10, 55 C => 10, 65 C => 100 + sensors -j | + jq '[.[]["temp1"]["temp1_input"]] | + (max-55)*(100/(65-55)) | + if . < 50 then 50 else if . > 100 then 100 else .|floor end end'; +# if . < 25 then 25 else if . > 100 then 100 else .|floor end end'; +} + +degrees=$(echo "$@" | perl -ne '/(\d+)C/i and print $1') + +if [ -z "$degrees" ] ; then + setfanspeed "$@" +else + runthreshold "$degrees" +fi diff --git a/field/field b/field/field index 385aa63..1398001 100755 --- a/field/field +++ b/field/field @@ -29,6 +29,10 @@ Select field 2,3,4,5: field 2-5 file +Select field 2,1,3,5,7,9,13: + + field 2,1-13/2 file + Select field 2..end: field 2- file @@ -78,8 +82,16 @@ sub range_to_fields { my @ranges = split(/,/, shift); my @fields; for (@ranges) { + # 2 /^(\d+)$/ and push (@fields,($1-1)); + # 2-11 /^(\d+)-(\d+)$/ and push (@fields,($1-1) .. ($2-1)); + # 3-19/2 + /^(\d+)-(\d+)\/(\d+)$/ and do { + for(my $t = $1; $t <= $2; $t += $3) { + push (@fields,($t-1)); + } + }; /^(\d+)-$/ and do { push (@fields,($1-1)." .. \$#F"); $Global::must_eval = 1; diff --git a/find-first-fail/find-first-fail b/find-first-fail/find-first-fail index fbd10b0..a7ddf90 100755 --- a/find-first-fail/find-first-fail +++ b/find-first-fail/find-first-fail @@ -5,14 +5,15 @@ =head1 NAME -find-first-fail - fine function for finding first failing file fragment +find-first-fail - fine function for finding first failing file +fragment (or numeric argument) =head1 SYNOPSIS -B [-2] [-q] [-s I] [-v] I +B [-2] [-q] [-s I] [-v] [-V] I -B -f I [-s I] [-q] [-v] I +B -f I [-s I] [-q] [-v] [-V] I =head1 DESCRIPTION @@ -144,6 +145,11 @@ To identify the minimal CSV file that causes myparser to fail: find-first-fail -f example.csv -s1 myparser +=head1 REPORTING BUGS + +Report bugs: https://gitlab.com/ole.tange/tangetools/-/issues + + =head1 AUTHOR Copyright (C) 2020 Ole Tange, @@ -185,7 +191,7 @@ find-first-fail() { shift shift local middle=$(( ( $low + $high ) / 2 )) - if _run $low $middle "$@" ; then + if _run $low $middle $high "$@" ; then low=$middle else high=$middle @@ -211,13 +217,15 @@ find-first-fail() { } local a="$1" local b="$2" + local c="$3" + shift shift shift local cmd=("$@") if $opt2 ; then $verbose && echo "$a&2 else - $verbose && echo "$a&2 + $verbose && echo "$a&2 fi eval "$not" _inner_run "$quiet" } @@ -225,7 +233,7 @@ find-first-fail() { _find_in_arg() { # If function(1) = false: run 'not function()' instead local not - if _run "$start" "$start" "$@" ; then + if _run "$start" "$start" "?" "$@" ; then not='' else not='!' @@ -236,7 +244,7 @@ find-first-fail() { # high = low * 2 (function($high) == false) local high=$(( $start*2 )) local low=$start - while _run $start $high "$@" ; do + while _run $low $high "?" "$@" ; do low=$high high=$(( $high*2 )) if [ $high -gt 4611686018427387900 ] ; then @@ -356,6 +364,18 @@ find-first-fail() { unset low high start quiet } + version() { + cat < +This is free software: you are free to change and redistribute it. +find-first-fail comes with no warranty. + +Web site: https://gitlab.com/ole.tange/tangetools/-/tree/master/find-first-fail +EOF +} + local opt2=false local optf=false local inputfile @@ -365,13 +385,14 @@ find-first-fail() { unset OPTIND # Parse and remove options - while getopts "2f:qs:v" options; do + while getopts "2f:qs:vV" options; do case "${options}" in (2) opt2=true;; (f) optf=true; inputfile="$OPTARG";; (q) quiet=">/dev/null 2>/dev/null";; (s) start="$OPTARG";; (v) verbose=true;; + (V) version; exit 0;; (-) break;; esac done @@ -389,6 +410,27 @@ find-first-fail() { fi _find_in_arg "$@"; fi + # TODO find-optimal: + # instead of looking at exit value, look at last line + # start=--start || 1 + # end=--end + # vstart = test(start) + # if end: + # vmiddle = test( (start+end)/2) + # if vstart < vmiddle: + # Search hill(start,end) + # else + # Search valley(start,t) + # else + # min = vstart + # max = vstart + # t = start*2 + # while t < big: + # v = test(t) + # if v < max and vstart < max: Search hill(start,t) + # if min < v and min < vstart: Search valley(start,t) + # t = t*2 + # fi } if [ -z "$*" ] ; then diff --git a/pidcmd/pidcmd b/pidcmd/pidcmd index aed2e48..d1efe8a 100755 --- a/pidcmd/pidcmd +++ b/pidcmd/pidcmd @@ -70,7 +70,8 @@ B =cut -for pid in "$@"; do +# $@ instead of "$@" to ignore spaces +for pid in $@; do cat /proc/$pid/cmdline | xargs -0 done diff --git a/plotpipe/README b/plotpipe/README index e1c92e3..d535157 100644 --- a/plotpipe/README +++ b/plotpipe/README @@ -29,11 +29,12 @@ Examples: seq 1 100 | shuf | plotpipe paste <(seq 1 100) <(seq 1 100) <(seq 1 100 | shuf) | plotpipe (echo "#Title"; echo "#Subtitle"; - echo "Column1 Column2 Column3"; + printf "Column1\tColumn2\tColumn3"; paste <(seq 1 100) <(seq 1 100) <(seq 1 100 | shuf) ) | plotpipe Copyright (C) 2020 Ole Tange, http://ole.tange.dk and Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. GNU plotpipe comes with no warranty. diff --git a/plotpipe/plotpipe b/plotpipe/plotpipe index 59c12c8..dd39460 100755 --- a/plotpipe/plotpipe +++ b/plotpipe/plotpipe @@ -123,6 +123,21 @@ input.csv: cat input.csv | plotpipe +=head1 LIMITS + +B is limited by Gnuplot. + +13x113425 = 28 MB +43x13203 = 10 MB +43x24068 = 5.8 MB +10x315636 +Gnuplot will complain: + + line -1: warning: Cannot find or open file "/tmp/plotXXXXX" + +if the input is too big. The plot will then be incomplete. + + =head1 AUTHOR Copyright (C) 2019-2020 Ole Tange, @@ -303,7 +318,7 @@ sub find_sep(@) { Getopt::Long::Configure("bundling","require_order"); my $retval = GetOptions(options_hash()); $Global::progname = "plotpipe"; -$Global::version = 20201125; +$Global::version = 20201222; if($opt::version) { version(); exit 0; } if($opt::help) { help(); exit 0; } if($opt::null) { $/ = "\0"; } @@ -356,7 +371,7 @@ if($ncols >= 2 and not $opt::nox) { } } else { # All data = y-axis, invent x-axis - my $x = 1; + my $x = 0; for(@csv) { chomp; print $filehandle ((join "\001", $x++, split /$opt::colsep/, $_),"\n"); @@ -397,13 +412,7 @@ set datafile separator "\001"; plot @plotscript _EOS -if(fork) { - open GNUPLOT,"|-", "gnuplot -p -e ".Q($plotscript) or die; - #print "gnuplot -p -e ".($plotscript); - close GNUPLOT; - unlink $filename; -} else { - # If script dies unexpectedly, remove the file after 5 sec - sleep(5); - unlink $filename; -} +open GNUPLOT,"|-", "gnuplot -p -e ".Q($plotscript) or die; +close GNUPLOT; +# print "gnuplot -p -e ".($plotscript); +unlink $filename;