I ping a series of addresses and append the latency results to a file (each address has a separate file). I'm trying to limit the file to only contain the last 2 entries.
$outpath=/opt/blah/file.txt
resp_str="0.42"
echo $resp_str >> $outpath
tail -2 $outpath > $outpath
Without tail, the file continues to grow with the new data (simply .42 for this example). But when I call tail, it writes out an empty file. If I redirect the tail output to a file of a different name, then I get the expected result. Can I not write out to a file as I read it? Is there a simple solution?
Here's the complete script:
OUT_PATH=/opt/blah/sites/
TEST_FILE=/opt/blah/test.txt
while IFS=, read -r ip name; do
if [[ "$ip" != \#* ]]; then
RESP_STR=$( ping -c 1 -q $ip | grep rtt| awk '{print $4}' | awk -F/ '{ print $2; }')
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
fi
done << $TEST_FILE
CodePudding user response:
You can use pipe |
to send the output of one commande to another, in this case tail.
We can then append out to a file using >>
. If we use >
we overwrite the file each time and all previous content is lost.
This example writes the 2 last files in the directory to log.txt each time it is run.
ls | tail -2 >> log.txt
CodePudding user response:
Assumptions:
- need to code for parallel, concurrent processes (use of temp files will require each process to have a uniquely named temp file)
- go ahead and code to support a high volume of operations (ie, reduce overhead of creating/destroying temp files)
One idea using mktemp
to create a temporary file ... we'll wrap this in a function for easier use:
keep2 () {
# Usage: keep2 filename "new line of text"
[[ ! -f "${tmpfile}" ]] &&
tmpfile=$(mktemp)
tail -1 "$1" > "${tmpfile}"
{ cat "${tmpfile}"; echo "$2"; } > "$1"
}
NOTES:
- the hardcoded
-1
(tail -1
) could be parameterized or reference a user-defined env variable - OP can change the order of the input parameters as desired
Taking for a test drive;
> logfile
for ((i=1;i<=5;i ))
do
echo "######### $i"
keep2 logfile "$i"
cat logfile
done
This generates:
######### 1
1
######### 2
1
2
######### 3
2
3
######### 4
3
4
######### 5
4
5
In OP's code the following line:
echo $RESP_STR >> "$OUT_PATH""test/"$name".txt"
would be replaced with:
keep2 "$OUT_PATH""test/"$name".txt" "${RESP_STR}"
CodePudding user response:
tail -2 $outpath > $outpath
>
truncates the file before tail
starts reading it.
You need to buffer the output of tail
before writing it back to that file. Use sponge to achieve this:
tail -2 $outpath | sponge $outpath