Home > Blockchain >  limiting file output to only 2 lines
limiting file output to only 2 lines

Time:05-04

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
  •  Tags:  
  • bash
  • Related