0

I have a bash script that is supposed to run periodically. the script should connect to a remote SFTP server and get a file from there. Since this is a SFTP server I had to use expect with the bash script. the script runs well when I run it manually but fails when running via crontab. the problematic function is the get_JSON_file() please advise...

this is the code:

#!/bin/bash

export xxxxx
export xxxxx
export PATH=xxxxx

check_if_file_is_open(){
while :
do
    if ! [[ `lsof | grep file.txt` ]]
    then
        break
    fi
    sleep 1
done
}


get_JSON_file(){
/usr/bin/expect -f <(cat << EOF
spawn sftp -P port user@ip
expect "Password:"
send "password\r"
expect "$ "
send "get path/to/file/file.json\r"
send "exit\r"
interact
EOF
)
}


get_JSON_file
check_if_file_is_open
cp file.txt /path/to/destination/folder
pynexj
  • 19,215
  • 5
  • 38
  • 56
Miki
  • 23
  • 4

4 Answers4

3

Expect's interact works only when stdin is on a tty/pty but cron job is not running on tty/pty. So replace interact with expect eof (or expect -timeout 12345 eof if necessary).

pynexj
  • 19,215
  • 5
  • 38
  • 56
  • SEE ALSO: [Expect script works while invoking individually but not as a Salt State](https://stackoverflow.com/questions/50698791/) – pynexj Sep 06 '18 at 15:59
1

That's a very awkward way to pass expect commands to the expect interpreter. Use a (quoted) heredoc instead, and you would drop the -f option for expect

get_JSON_file(){
    /usr/bin/expect <<'EOF'
        spawn sftp -P port user@ip
        expect "Password:"
        send "password\r"
        expect "$ "
        send "get path/to/file/file.json\r"
        send "exit\r"
        expect eof
EOF
}

The most important tip for debugging expect scripts is to invoke expect's debug output. While you're working out the kinks, use

expect -d <<'EOF'

and in the crontab, you'd want to redirect stderr to stdout so you get the debugging output

* * * * * /path/to/script.sh 2>&1
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

To run a function within a shell script, no parentheses should be used.

Your code then becomes:

#!/bin/bash

export xxxxx
export xxxxx
export PATH=xxxxx

function check_if_file_is_open(){
while :
do
    if ! [[ `lsof | grep file.txt` ]]
    then
        break
    fi
    sleep 1
done
}


function get_JSON_file(){
/usr/bin/expect -f <(cat << EOF
spawn sftp -P port user@ip
expect "Password:"
send "password\r"
expect "$ "
send "get path/to/file/file.json\r"
send "exit\r"
interact
EOF
)
}


get_JSON_file
check_if_file_is_open
cp file.txt /path/to/destination/folder
Mitms
  • 571
  • 4
  • 7
  • This is an important fix, but does nothing to address the various other flaws and inefficiencies in the OP's script. – tripleee Sep 06 '18 at 10:32
  • I don't have parentheses, when i call the function. I added it by mistake here)) the main issue is that the sftp commands are not being executed (or being executed not properly) – Miki Sep 06 '18 at 12:00
  • Oops, sorry. That was the one obvious mistake I saw. I'm no expert on using the sftp tool, since I mostly fetch files using cURL or wget (well maybe also scp/rsync). This can be automated pretty easily and can omit a -send/expect/interact- construction. – Mitms Sep 20 '18 at 07:12
0

create a new script with screen command and add it in crontab

new_script.sh
#!/bin/bash
cd script_path
screen -dm -S screen_name ./your_script.sh