date +%F "$@"
}
-# timestamp in log appropriate format
+# Timestamp in log appropriate format. A filename friendly format is date +%y-%m-%d_%H-%M-%S
dtl() {
date "+%F %T" "$@"
}
user=$USER
while [[ $1 ]]; do
case $1 in
+ -u)
+ alt_user=true
+ user="$2"
+ shift 2
+ ;;
-p)
# note: this must call mns-setup
pre_check="$2"
shift
env-tmpf "$@"
+ if $alt_user; then
+ final_args=("$@")
+ else
+ final_args=(bash -c ". $tmpf")
+ fi
if [[ $pre_check ]]; then
sudm $pre_check
mns-setup $ns
fi
- m sudm nsenter --mount=/root/mount_namespaces/$ns sudo -u iank -i bash -c ". $tmpf"
+ m sudm nsenter --mount=/root/mount_namespaces/$ns sudo -u $user -i "${final_args[@]}"
}
mnsd() { # mount namespace + systemd network namespace
# for mitmproxy to get a newer python.
# commented until i want to use it because it
-# noticably slows bash startup
-#
+# noticably slows bash startup.
+
+
mypyenvinit () {
if [[ $EUID == 0 || ! -e ~/.pyenv/bin ]]; then
return 1
fi
export PATH="$HOME/.pyenv/bin:$PATH"
- eval "$(pyenv init -)"
- eval "$(pyenv virtualenv-init -)"
+ # not sure this is actually used.
+ export PYENV_ROOT="$HOME/.pyenv"
+ eval "$(pyenv init - bash)"
}
# However, options 08+ do not work. Perhaps the user settings need setup first.
}
+trailcam-dl() {
+ dir=$1
+ if [[ ! $1 ]]; then e $0: error: no dir arg given; return 1; fi
+ c /t/trailcam
+ s mount /dev/sdo1 /mnt/1
+ time s rsync -ra /mnt/1/DCIM/100MEDIA/ $dir
+ s chown -R iank:iank $dir
+ s umount /mnt/1
+}
+
+psq-exdoc () {
+ local file="$1"
+ sed -ri '/\* iankqmark/,$d' "$file"
+ psql dl <<<"\i $file" | /a/c/psq-ex | pee cat "sponge -a $file"
+}
export BASEFILE_DIR=/a/bin/fai-basefiles
done
#### begin special extra stuff ####
+
+
+ if [[ $HOSTNAME == frodo ]]; then
+ m rsync -clpgoDiSAX --chown=root:root /b/bash_unpublished/i3-misc1 /usr/local/bin
+ fi
+
install -d -oiank -giank -m700 /home/iank/gpg-agent-socket
if [[ -e /p/c/user-specific/prometheus ]]; then
bindsym $mod+e $ex "i3-emacs"
# unused
-#bindsym $mod+shift+e
+bindsym $mod+shift+e $ex "sudo i3-misc1"
bindsym $mod+r $ex "/a/bin/ds/xl"
bindsym $mod+backslash $ex "scrot"
for service; do
# ignore services that dont exist
if systemctl cat $service &>/dev/null; then
+ # note: we avoid using --now enable because if starting the
+ # service fails, the command still succeeds.
m systemctl disable --now $service
fi
done
fi
done
}
-sgo() {
- local service
+son() {
+ local enabled service
for service; do
- systemctl restart $service
- systemctl enable $service
+ enabled=$(systemctl is-enabled $service 2>/dev/null ||:)
+ if [[ $enabled != enabled ]]; then
+ m systemctl enable $service
+ fi
+ m systemctl start $service
done
}
mailhost() {
fi
if spamd-timer-exists; then
- systemctl enable --now spamassassin-maintenance.timer
+ son spamassassin-maintenance.timer
fi
# note: pyzor debian readme says you need to run some initialization command
sudo sed -i --follow-symlinks 's/^ *hosts:.*/hosts: files dns myhostname/' /etc/nsswitch.conf
soff systemd-resolved
sudo ln -sf 127.0.0.1-resolv/stub-resolv.conf /etc/resolv.conf
- sgo unbound
+ sre unbound
# cautious measure to make sure resolution is working
sleep 1
;;
case $HOSTNAME in
bk)
- sgo named
+ sre named
;;
esac
[Install]
WantedBy=timers.target
EOF
- systemctl enable --now $ncbase.timer
+ son $ncbase.timer
u /usr/local/bin/ncup <<'EOFOUTER'
#!/bin/bash
# checking bhost_t is redundant, but could help us catch errors.
if $bhost_t || [[ -e /etc/wireguard/wghole.conf ]]; then
# todo: in mail-setup, we have a static list of backup hosts, not *y
- m systemctl --now enable wg-quick@wghole
+ sre wg-quick@wghole
fi
fi
# optimization, this only needs to be run once
if [[ ! -e /var/lib/prometheus/node-exporter/exim_paniclog.prom ]]; then
sysd-prom-fail-install epanicclean
- m systemctl --now enable epanicclean
+ sre enable epanicclean
fi
case $HOSTNAME in
# Existence check is just to avoid ugly error message from openssl.
if [[ ! -e /etc/exim4/fullchain.pem ]] || ! openssl x509 -checkend $(( 60 * 60 * 24 * 3 )) -noout -in /etc/exim4/fullchain.pem; then
m /a/bin/ds/mail-cert-cron -1 -i
- m systemctl --now enable mailcert.timer
+ son mailcert.timer
fi
case $HOSTNAME in
$MAIL_HOST|bk)
# If any of these have config changes, then restart them as needed:
# sre mailnn mailnnroute $vpnser
- m systemctl --now enable mailnn mailnnroute $vpnser
+ son mailnn mailnnroute $vpnser
;;&
$MAIL_HOST)
# If this service's config changes, add a manual restart here.
# note: we use dns to start wireguard
- m systemctl --now enable unbound
+ son unbound
;;&
bk)
if ! systemctl is-active clamav-daemon >/dev/null; then
- m systemctl --now enable clamav-daemon
+ son clamav-daemon
out=$(rsync -aiSAX --chown=root:root --chmod=g-s /a/bin/ds/filesystem/etc/systemd/system/epanicclean.service /etc/systemd/system)
if [[ $out ]]; then
reload=true
# of waiting. I'll deal with this some other way.
#
# sleep 3
- m systemctl --now enable mailclean.timer
+ son mailclean.timer
;;&
$MAIL_HOST)
# < 2.1 (eg: in t9), uses a different data format which required manual
# migration. dont start if we are running an old version.
if dpkg --compare-versions "$(dpkg -s radicale | awk '$1 == "Version:" { print $2 }')" ge 2.1; then
- m systemctl --now enable radicale
+ son radicale
fi
;;&
esac
# for debugging dns issues
case $HOSTNAME in
je|bk)
- systemctl enable --now logrotate-fast.timer
+ son logrotate-fast.timer
;;
esac
case $HOSTNAME in
$MAIL_HOST)
- m systemctl --now enable mailbindwatchdog
+ sre mailbindwatchdog
;;
*)
soff mailbindwatchdog
libdata-types-perl
libdbd-pg-perl
libfile-libmagic-perl
+ libcrypt-urandom-perl
fakeroot
fail2ban
fdupes
--- /dev/null
+#!/usr/bin/perl
+use v5.38;
+use warnings FATAL => 'all';
+no autovivification; # libautovivification-perl
+use utf8;
+use open ':std', ':encoding(UTF-8)';
+use File::Glob ':bsd_glob';
+# Note meta chars: \ [] * ?, test with =~ /[\\[\]*?]/ . avoid glob() it splits pattern on spaces.
+sub glo {
+ my ($pattern, $flags) = @_;
+ $flags //= GLOB_ERR | GLOB_NOSORT | GLOB_QUOTE;
+ my @results = bsd_glob($pattern, $flags);
+ if (GLOB_ERROR) { die "GLOB_ERROR: " . GLOB_ERROR . " pattern:'$pattern', \$!:$!"; }
+ return @results;
+}
+
+sub process_number {
+ my ($num) = @_;
+
+ # Remove decimal part and convert to integer
+ $num = int($num);
+ $num = int($num / 10_000);
+
+ return "0" if $num <= 0;
+
+ # Keep only first 2 digits, set rest to 0
+ my $str = "$num";
+ my $len = length($str);
+
+ if ($len > 2) {
+ my $first_two = substr($str, 0, 2);
+ my $zeros = "0" x ($len - 2);
+ $num = int($first_two . $zeros);
+ }
+ #say "debug num $num"
+
+ # Add commas
+ my $formatted = reverse $num;
+ $formatted =~ s/(\d{3})(?=\d)/$1,/g;
+ $formatted = reverse $formatted;
+
+ return $formatted;
+}
+
+my $input_file = $ARGV[0];
+my $output_file = $ARGV[1];
+
+my $input_fh;
+my $output_fh;
+
+if ($input_file) {
+ open($input_fh, '<', $input_file) or die "Cannot open input file '$input_file': $!";
+} else {
+ $input_fh = \*STDIN;
+}
+
+if ($output_file) {
+ open($output_fh, '>', $output_file) or die "Cannot open output file '$output_file': $!";
+} else {
+ $output_fh = \*STDOUT;
+}
+
+my @lines = ();
+my @cost_values = ();
+
+print $output_fh "/* iankqmark\n";
+# Process each line
+while (my $line = <$input_fh>) {
+
+ my $original_line = $line;
+ my $second_cost = 0;
+
+ # Extract second cost value before processing
+ if ($line =~ /cost=\d+(?:\.\d+)?\.\.(\d+(?:\.\d+)?)/) {
+ $second_cost = $1;
+ # Apply the same reduction rules to get the sorting value
+ $second_cost = int($second_cost);
+ $second_cost = int($second_cost / 10_000);
+ $second_cost = 0 if $second_cost <= 0;
+ }
+
+
+ # cost=number..number or cost=number
+ $line =~ s/cost=(\d+(?:\.\d+)?)\.\.(\d+(?:\.\d+)?)/
+ "cost=" . process_number($1) . ".." . process_number($2)/ge;
+
+ #$line =~ s/cost=(\d+(?:\.\d+)?)(?!\.)/"cost=" . process_number($1)/ge;
+
+ # rows=number
+ $line =~ s/rows=(\d+(?:\.\d+)?)/"rows=" . process_number($1)/ge;
+
+ # width=number
+ #$line =~ s/width=(\d+(?:\.\d+)?)/"width=" . process_number($1)/ge;
+
+ # Match loops patterns: loops=number
+ $line =~ s/loops=(\d+(?:\.\d+)?)/"loops=" . process_number($1)/ge;
+
+ push @lines, {
+ processed_line => $line,
+ second_cost => $second_cost,
+ original_index => scalar(@lines)
+ };
+
+ push @cost_values, $second_cost;
+
+}
+
+my @sorted_indices = sort {
+ $lines[$b]->{second_cost} <=> $lines[$a]->{second_cost} ||
+ $a <=> $b # Secondary sort by original line order for ties
+} 0..$#lines;
+
+my %rank_map = ();
+my $rank = 1;
+for my $i (0..$#sorted_indices) {
+ last if $rank > 9;
+ my $idx = $sorted_indices[$i];
+ if ($lines[$idx]->{second_cost} > 0) {
+ $rank_map{$idx} = $rank;
+ $rank++;
+ }
+}
+
+# Output lines in original order with rank replacements
+for my $i (0..$#lines) {
+ my $output_line = $lines[$i]->{processed_line};
+
+ # Replace first character with rank if this line is in top 9
+ if (exists $rank_map{$i}) {
+ substr($output_line, 0, 1) = $rank_map{$i};
+ }
+
+ print $output_fh $output_line;
+}
+
+print $output_fh "\n*/\n";
+
+# Close file handles
+close($input_fh) if $input_file;
+close($output_fh) if $output_file;