cronjob의 SFTP 업로드 파일

cronjob의 SFTP 업로드 파일

SFTP를 사용하여 A에서 B로 파일을 업로드하고 싶습니다.

A의 경로: /tmp/AB의 경로: /tmp/B

서버 B에는 자체 사용자 이름과 비밀번호가 있습니다. 내 cronjob은 10분마다 실행되며 /tmp/A 아래에 새 파일이 있는지 확인하고 파일이 있으면 전송하고 그렇지 않으면 전송하지 않습니다.

답변1

이를 수행하려면 rsync 명령을 사용할 수 있습니다.

rsync를 사용하여 원격 시스템과 동기화하는 방법

원격 시스템에 대한 SSH 액세스 권한이 있고 양쪽 모두 rsync가 설치되어 있는 경우 원격 시스템과의 동기화는 간단합니다. SSH 키를 설정해야 합니다. 자세한 방법은 다음과 같습니다.https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys--2

두 시스템 간의 SSH 액세스를 확인한 후에는 다음 구문을 사용하여 이전 폴더의 dir1 폴더를 원격 시스템으로 동기화할 수 있습니다(이 경우 실제 디렉터리를 전송하려고 하므로 후행 슬래시를 생략합니다).

rsync -avz ~/dir1 username@remote_host:destination_directory

이를 로컬 시스템에서 원격 시스템으로 디렉터리를 푸시하므로 "푸시" 작업이라고 합니다.

답변2

올바르게 이해했다면 일부 SFTP 서버는 SSH 키를 지원하지 않으므로 rsync가 작동하지 않는다는 것을 알았습니다(예:reports.paypal.com). 이 경우 SFTP 작업을 수행하는 스크립트를 작성해야 합니다. Expect를 사용하여 이 작업을 수행할 수 있습니다. 다음은 스크립트입니다.

#!/bin/sh

bname=`basename $0`

usage () #usage instructions
{
  cat <<EOF
  syncs LOCALPATH to REMOTEPATH on sftp://SERVICE

  Usage : ./$bname [-s SERVICE -l LOCALPATH -r REMOTEPATH] [-h]
    -h  display this help text.

  Example: ./$bname -s your.sftpserver.com -l /tmp/A -r /tmp/B
            will upload any missing files from /tmp/A to /tmp/B

EOF
  exit 0
}

upload ()
{
  security find-generic-password -s _$SERVICE_sftp >/dev/null 2>/dev/null #test if entry exists in keychain
  if [ $? -ne 0 ]; then
    echo "Please enter username for sftp://"$SERVICE
    read username
    echo $username > .credentials_tmp
    read -p "Password:" -s pass
    echo $pass >> .credentials_tmp
  else
    echo `security find-generic-password -s _$SERVICE_sftp | grep "acct" | cut -d \" -f 4` > .credentials_tmp
    echo `security find-generic-password -s _$SERVICE_sftp -w` >> .credentials_tmp
  fi
  echo $SERVICE >> .credentials_tmp
  echo $REMOTEPATH >> .credentials_tmp
  echo $LOCALPATH >> .credentials_tmp
  ls -1 $LOCALPATH > .LocalFileList.txt
  echo "
Connecting to sftp://"$SERVICE
  expect << 'EOS'
  log_user 0
  set send_human {.1 .3 1 .05 2}
  spawn sftp [exec sed "1p;d" .credentials_tmp]@[exec sed "3p;d" .credentials_tmp]:[exec sed "4p;d" .credentials_tmp]
  set timeout 30
  expect {
    "Password:" {
    # exp_continue
    } timeout {
    send_user "
  *** Connection timed out. Check connection and verify the username/password"; exit 1
    }
  }
  puts "Authenticating"
  send "[exec sed "2p;d" .credentials_tmp]\n"
  #log_user 1
  expect {
    "sftp>" {
    # exp_continue
    } timeout {
    send_user "
  *** Connection timed out. Check connection"; exit 1
    }
  }
  puts "Getting Remote File List"
  log_file -a -noappend .RemoteFileList.txt
  send "ls -1\n"
  expect {
    "sftp>" {
    # exp_continue
    } timeout {
    send_user "
  *** Connection timed out. Check connection"; exit 1
    }
  }
  log_file
  system sed -i '' '/ls -1/d' ./.RemoteFileList.txt
  system sed -i '' '/sftp>/d' ./.RemoteFileList.txt
  puts "Comparing with files in [exec sed "5p;d" .credentials_tmp]"
  sleep 1
  set rc [catch {exec diff -aw --changed-group-format=%< --unchanged-group-format= .LocalFileList.txt .RemoteFileList.txt} output]
  if {$rc == 0} {
    puts "no difference"
  } else {
    if {[lindex $::errorCode 0] eq "CHILDSTATUS"} {
      if {[lindex $::errorCode 2] == 1} {
        # send output without "child process exited abnormally" message
        set filename ".newfiles.txt"
        set fileId [open $filename "w"]
        puts -nonewline $fileId [string replace $output end-31 end ""]
        close $fileId
      } else {
        puts "diff error: $output"
      }
    } else {
      puts "error calling diff: $output"
    }
  }
  sleep 1
  if {[file size .newfiles.txt] == 0} {
    sleep 1
    send "bye\n"
    puts "
There are no local files missing from the remote server"
    interact
  } else {
    set f [open ".newfiles.txt"]
    while {[gets $f line] != -1} {
      send "put [exec sed "5p;d" .credentials_tmp]/$line\n"
      puts "Uploading $line..."
      expect {
        "sftp>" {
        # exp_continue
        } timeout {
        send_user "
      *** Connection timed out. Check connection"; exit 1
        }
      }
  }
  close $f
  send "bye\r"
  puts "
Finished syncing from [exec sed "5p;d" .credentials_tmp] to sftp://[exec sed "3p;d" .credentials_tmp]:[exec sed "4p;d" .credentials_tmp]"
  }
EOS
security find-generic-password -s _$SERVICE_sftp >/dev/null 2>/dev/null #test if entry exists in osx keychain
if [ $? -ne 0 ]; then
  while true; do
  read -p "
Do you want to save these login details for next time?
y/n " yn
    case $yn in
      [Yy]* )
        security add-generic-password -s _$SERVICE_sftp -a `sed '1p;d' .credentials_tmp` -w `sed '2p;d' .credentials_tmp` -U
        rm -f .credentials_tmp
        echo "credentials saved."
        break
        ;;
      [Nn]* )
        rm -f .credentials_tmp
        exit 1
        ;;
      * ) echo "Please answer yes or no.
y/n ";;
    esac
  done
fi
rm -f .credentials_tmp
rm -f .newfiles.txt
rm -f .LocalFileList.txt
rm -f .RemoteFileList.txt
}

# From here down is all to do with handling the flags you type into the command line, after the name of the script.
if [ ! $# == 6 ] || [ "$1" = "-h" ] || [ "$1" = "-" ]
then
  usage
fi

while getopts ":s:l:r:" opt; do
  case $opt in
    s) SERVICE=$OPTARG;;
    l) LOCALPATH=$OPTARG;;
    r) REMOTEPATH=$OPTARG;;
    \?)
      echo "Invalid option: -$OPTARG
      type ./"$bname" -h for help
      " >&2
      exit 1
      ;;
  esac
  #shift $(( OPTIND - 1 ))
done
upload $SERVICE $LOCALPATH $REMOTEPATH

사용하려면 uploadsftp.sh와 같은 파일에 코드를 저장하고 실행하면 됩니다.chmod u+x uploadsftp.sh

./uploadsftp.sh -s SERVICE -l LOCALPATH -r REMOTEPATH그런 다음 cron을 스크립트 디렉토리에 cd로 설정하고 필요할 때마다 스크립트를 실행할 수 있습니다 .

관련 정보