1

I want to count the number of files of a given type on a remote server. For that I need to ssh and run the commands to count the files on the remote server and then somehow return that value. I thought about just printing the value and trying to capture that output

What I have so far is:

START=0
LAST=5
ssh -i $KEY $USERNAME@$HOST << EOF

  N_FILES=0;
  for (( d=$START; d<=$LAST; d++ ))
  do
        check_day=`date +"%Y-%m-%d" -d "$d day ago"`

        FILES_FOUND="\$(find &DIR | grep $check_day | wc -l)"

        N_FILES=\$(( \$N_FILES + \$FILES_FOUND ))

  done
  echo $N_FILES

EOF
N_FILES=$?

The above code runs fine but yields 0, when there are actually files found in the server co capturing the output this way is not working. Can somebody help here please?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
daniel
  • 31
  • 3
  • 1
    `$?` is the exit code of the last command, not the captured output. Your script will always exit with success, so it'll always be 0. – Aplet123 Dec 12 '20 at 16:19
  • You need to escape the a number of `$` characters and backticks in the here-document, so they don't get expanded on the local system before being sent over `ssh`. To debug this, try replacing `ssh -i $KEY $USERNAME@$HOST` with `cat` to see what's actually being sent to the remote system. Oh, and there's almost certainly a better way to check the last five days than scanning and grepping five times. Are the dates part of the filename or something? – Gordon Davisson Dec 12 '20 at 18:03

2 Answers2

0

You could simply assign the result of the SSH command to a variable:

IFS="" N_FILES=$(ssh -Ti $KEY $USERNAME@$HOST << EOF

  N_FILES=0;
  for (( d=$START; d<=$LAST; d++ ))
  do
        check_day=`date +"%Y-%m-%d" -d "$d day ago"`

        FILES_FOUND="\$(find &DIR | grep $check_day | wc -l)"

        N_FILES=\$(( \$N_FILES + \$FILES_FOUND ))

  done
  echo $N_FILES

EOF
)
echo $N_FILES

Note: the N_FILES before ssh is not the same N_FILES used inside the ssh command.
But its value (provided none of the other ssh commands have any output) will be the same.

The -T seems important here: no need to request a pseudo-TTY to assign the output to a variable.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Hi VonC, thank you for your answer. I tried it but unfortunately it is not working. Nothing seems to be returned from the ssh command. To debug it I ve simplified the code to ``` N_FILES=$(ssh -i $KEY $USERNAME@$HOST << EOF N_FILES=0; echo $N_FILES EOF ) echo $N_FILES ``` but nothing gets printed, so it seems that nothing is being returned from the ssh command. Any tips» – daniel Dec 12 '20 at 18:12
  • @daniel First, don't forget the `IFS=""` before the command, to get the newlines. Second, add a -T to your SSH command `ssh -Ti ...`. – VonC Dec 12 '20 at 19:20
0

Here's my hacky solution. This code is not perfect and I'm sure that there are other elegant and efficient methods than this. But here goes.

I'm going to create a cmds.txt file with the input commands to run on the remote server and the output from the remote server will be saved in another file out.txt.

By separating the input command in a separate file, it will become easier to modify code.

Also, saving the output to a text file, will preserve the output by preserving line breaks; Helpful when we need to fetch multi-line output from the remote server.

Contents of cmds.txt

Code placed here will be executed in remote server
N_FILES=0;
  for (( d=$START; d<=$LAST; d++ ))
  do
        check_day=`date +"%Y-%m-%d" -d "$d day ago"`

        FILES_FOUND="\$(find &DIR | grep $check_day | wc -l)"

        N_FILES=\$(( \$N_FILES + \$FILES_FOUND ))

  done
  echo $N_FILES

Contents of script.sh

#!/bin/bash
cmd=$(cat cmds.txt)
/usr/bin/ssh -o StrictHostKeyChecking=no ssh -i $KEY $USERNAME@$HOST "$cmd" > out.txt


cat out.txt

secnigma
  • 1
  • 3