1

I need to execute a script on a remote server over ssh, I can't locate the script as a file on the remote server nor create files during the script process.

The script checks for a non existent or zero byte file, and if exists, checks if is outdated.

I've followed a thread here on SO and tried this:

myvar=$(ssh user@server <<EOF
myfile=/mnt/file.csv
if [ -s $myfile ]; then
   filedate=$(stat -c %x $myfile|grep '[0-9\-]*' --max-count=1 -o);
   yesterday=$(date --date 'now -1 day' --iso-8601);
   if [ $filedate < $yesterday ]; then
     echo '1 '$yesterday;
   else
     echo '0 ok';
   fi
else
   echo $(date --iso-8601);
fi
EOF
)

sadly, the pipe appears to be truncating the string or something, because the script returns

stat: too few arguments

maybe just cannot use "myfile" var declaration. Any suggestions?

Thanks in advance.

---- Edit: Clarifying answer:

keber-laptop:~ keberflores$ echo $myvar

keber-laptop:~ keberflores$ myvar=$(ssh user@server <<EOF
> myfile=/mnt/file.csv
> if [ -s \$myfile ]; then
>    filedate=\$(stat -c %x \$myfile|grep '[0-9\-]*' --max-count=1 -o);
>    yesterday=\$(date --date 'now -1 day' --iso-8601);
>    if [ \$filedate < \$yesterday ]; then
>      echo '1 '\$yesterday;
>    else
>      echo '0 ok';
>    fi
> else
>    echo '1 '\$(date --iso-8601);
> fi
> EOF
> )
Pseudo-terminal will not be allocated because stdin is not a terminal.
user@server's password: 
keber-laptop:~ keberflores$ echo $?
0
keber-laptop:~ keberflores$ echo $myvar
1 2011-10-22

---- Edit: calling inside perl:

my $myvar = qx'ssh user@server <<\'EOF\'
myfile=/mnt/file.csv
if [ -s $myfile ]; then
   filedate=$(stat -c %x $myfile|grep \'[0-9\-]*\' --max-count=1 -o);
   yesterday=$(date --date \'now -1 day\' --iso-8601);
   if [ $filedate < $yesterday ]; then
     echo \'1 \'$yesterday;
   else
     echo \'0 ok\';
   fi
else
   echo \'1 \'$(date --iso-8601);
fi
EOF
';
print $myvar;
Community
  • 1
  • 1
Keber
  • 61
  • 2
  • 9

1 Answers1

3

You need more escaping to get this to work. bash is going to evaluate the variables, etc in the here-file locally, then the result of that will be evaluated on the remote server.

In particular, your $myfile is probably evaluating to an empty string when the here-file is being evaluated, causing the stat to not have a file argument.

retracile
  • 12,167
  • 4
  • 35
  • 42
  • 1
    It's more than just the variables, the `$(stat ...)` and such are being executed on the local computer as well. Escaping the `$` characters (i.e. `filedate=\$(stat -c %x \$myfile| ...`) should solve it. You can test by replacing `myvar=$(ssh user@server` with `cat` (and remove the final close parenthesis), and it'll print the commands as they would be sent to the remote computer. – Gordon Davisson Oct 22 '11 at 04:26
  • 1
    try running the script and change the shebang to: #/bin/bash -x to see what's going on, it will display the output of variables, and whether conditions are met – Kevin Oct 22 '11 at 05:11
  • 1
    @GordonDavisson: Correct. I should have been explicit than "you need more escaping". :) – retracile Oct 22 '11 at 14:27
  • 2
    The fix is easy: add single quotes around the initial occurrence of `EOF`. – tripleee Oct 22 '11 at 15:29
  • @GordonDavisson, your point on cat to troubleshoot the vars helped a lot, both with retractile answer helped to solve my issue, THANKS! – Keber Oct 22 '11 at 17:14
  • @triplee: for some reason I was thinking there was one variable that needed to be evaluated locally, so escaping was needed to control local vs. remote. Apparently I was mistaken, all evaluations should be remote, so quoting `EOF` (and not escaping the `$`es) is indeed a simpler way to get the same effect. – Gordon Davisson Oct 22 '11 at 20:18
  • that's ok, the issue is that I need to make this call from a perl program, so really need to protect $ es to ensure the string goes complete to the remote server. Indeed, @triplee suggestion helped a lot, just needed to escape simple cuotes. – Keber Oct 24 '11 at 13:26