So, habe den Code noch etwas umgestrickt. Folgende Änderung: Man möchte ja nicht nur wissen ob was auf den Adressen passiert, sondern auch, ob die entsprechenden Blockexplorer funktionieren und wie sich die Balance geändert hat.
Die Balanceberechnung läuft nun über ein R-Skript (sum_balances.R), welches auch (mehr oder weniger gut) testet ob die Tabelle mit den Balances sauber aus den Explorern ausgelesen wurden. Für das R-Skript muss R installiert sein. Das geht aber leicht über:
sudo apt-get install r-base
Das R-Skript:
#!/usr/bin/env Rscript
# which files are to be compared
args <- commandArgs(TRUE);
# if data is not formatted correctly, we want a corresponding message
tryCatch(
{
old <- read.table(file=args[1], sep="\t", quote="");
new <- read.table(file=args[2], sep="\t", quote="");
},
error=function(cond){
cat("error reading files\n");
q();
},
warning=function(cond){
cat("warning reading files\n");
q();
},
finally={
}
)
# give the data frames column names
colnames(old) <- c("ADDRESS", "AMOUNT", "CURRENCY");
colnames(new) <- c("ADDRESS", "AMOUNT", "CURRENCY");
# amounts to numbers since we do not want factors
old[,"AMOUNT"] <- as.numeric(as.character(old[,"AMOUNT"]));
new[,"AMOUNT"] <- as.numeric(as.character(new[,"AMOUNT"]));
# test if all blockchain explorers responded
cold <- unique(old[,"CURRENCY"]);
cnew <- unique(new[,"CURRENCY"]);
if (length(cold) == length(cnew)){
cat("");
} else {
cat("currency missing, corresponding explorer might be down\n");
}
# get maximal number of currencies available in the files
currencies <- cold;
if (length(cnew) > length(cold))
currencies <- cnew;
v <- c(); # vector of deltas
for (currency in currencies){
# if all blockchain explorers worked (might still fail because explorer
# can be unresponsive for some addresses in case of much traffic)
if (currency %in% cold && currency %in% cnew){
aold <- sum(old[old[,"CURRENCY"]==currency,"AMOUNT"]);
anew <- sum(new[new[,"CURRENCY"]==currency,"AMOUNT"]);
v <- c(v, anew - aold);
}
# if explorer failed for currency in new file
if (currency %in% cold && !(currency %in% cnew)){
aold <- sum(old[old[,"CURRENCY"]==currency,"AMOUNT"]);
v <- c(v, 0 - aold);
}
# if explorer failed for currency in old file
if (!(currency %in% cold) && currency %in% cnew){
anew <- sum(new[new[,"CURRENCY"]==currency,"AMOUNT"]);
v <- c(v, anew - 0);
}
}
# test if deltas sum up to zero
if (sum(v) == 0){
cat("ok\n");
} else {
cat(paste(c(v, "\n"), collapse=" "));
}
Natürlich wieder ausführbar machen. Ich kann aber nicht garantieren, dass bei fehlerhaftem Auslesen der blockchains die Fehler auch sauber und wie geplant abgefangen werden. If-Abfragen könnten eleganer gelöst werden ...
Das Skript check_balances.sh muss auch angepasst werden:
#!/bin/bash
date=$(date);
epoch=$(date +%s);
path="/home/user/balances";
$path/balances.sh > $path/balances.$epoch.txt
old=$(find $path -name "balances.*.txt" | uniq | sort | tail -n2 | head -n1);
new=$(find $path -name "balances.*.txt" | uniq | sort | tail -n1);
echo "comparing $old with $new";
hold=$(md5sum $old | cut -d " " -f 1);
hnew=$(md5sum $new | cut -d " " -f 1);
echo "comparing $hold with $hnew";
# this is necessary for R producing no locale warnings, but might differ from OS to OS
LC_TIME=C;
LC_MONETARY=C;
LC_PAPER=C;
LC_MEASUREMENT=C;
out=$($path/sum_balances.R $old $new);
info="0";
if [[ "$out" == "ok" ]]
then
sleep 0;
#info=$(wget -qO- "http://api.lima-city.de/sms?user_id=
&apikey=&text=&number=");
else
sleep 0;
# to make sure, that we get a message only once
if [[ "hold" != "hnew" ]]
then
out="$date: $out";
info=$(wget -qO- "http://api.lima-city.de/sms?user_id=&apikey=&text=$out&number=");
fi
fi
echo "$out"
echo "$info"
Wenn alles funktionert bekommt man eine SMS der Form:
Sat May 5 15:02:28 CEST 2018: 0 0 0 0 0 0 100
Wobei Coin #7 100 Einheiten gut gemacht hat, alle anderen blieben gleich.