如何通过Bash脚本连接到FTP服务器?

5
我为从服务器上传备份文件到ftp服务器编写了一个bash脚本,但我一直遇到错误。
Name (myftpserver:root): Permission denied.
Login failed.
Login with USER first.
Please login with USER and PASS.
Local directory now /backup01
Please login with USER and PASS.
Passive mode refused.

这是我的脚本:

#!/bin/bash

DATE=`date +%Y-%m-%d_%H%M`
LOCAL_BACKUP_DIR="/backup01"
DB_NAME="databasename"
DB_USER="root"

FTP_SERVER="randomIP"
FTP_USERNAME="myname"
FTP_PASSWORT="supersecret"
FTP_UPLOAD_DIR="/home/mydirectory/ftp/upload"

LOG_FILE=/backup01/backup-$DATE.log

mysqldump -u $DB_USER  $DB_NAME | gzip  > $LOCAL_BACKUP_DIR/$DATE-$DB_NAME.sql.gz

ftp $FTP_SERVER << END_FTP
quote USER $FTP_USERNAME 
quote PASS $FTP_PASSWORD
cd $FTP_UPLOAD_DIR
lcd $LOCAL_BACKUP_DIR
put "$DATE-$DB_NAME.sql.gz"
bye
END_FTP


if test $? = 0
then
    echo "Database successfully uploaded to the FTP Server!"
    echo "Database successfully created and uploaded to the FTP Server!" | mail -s "Backup from $DATE" my.email@whereever.com

else
    echo "Error in database upload to Ftp Server" > $LOG_FILE
fi

可能有人能帮我,因为我已经尝试了在互联网上找到的所有方法。 我创建了一个 .netrc 文件。我配置了 vsftpd.conf,启用了被动模式、用户列表等等... 但是现在我不知道还需要做什么才能让这个脚本正常工作。而且我也不知道为什么它会尝试通过 root 连接...

也许有人能帮忙。 提前致谢。


1
你在这里看到 myftpserver:root 是因为脚本在使用 ftp 连接到远程 ftp 服务器时是在 root 下运行的。这与在 ftp 连接期间提供用户名不同。你可以手动使用 ftp 来验证这一点。 - GoinOff
1
使用 ftp -n 必须正常工作。就像下面的示例一样。 - Incrivel Monstro Verde
1
“here-doc” ftp脚本是基本的,但没有错误处理。不要在任何重要的事情上使用它们。对于0的“测试”仅确认“ftp”成功退出,而它会在输出中愉快地报告所有失败后退出。我编写了基于shell的循环,根据脚本读取和响应,但这是非平凡的。如果您可以使用“scp”,请尝试使用它。如果不能,请将刚刚发送的文件拉回到本地临时名称并比较发送和拉取。如果它们匹配,则拉取了您发送的文件,然后您可以删除临时文件并继续进行。 - Paul Hodges
1
@PaulHodges scp 是个好主意。它完美地运行了。谢谢。 - steff
你可以调用系统的ftp命令,通过标准输入将所有参数传递进去。但这样可能无法正常工作。相反,你可以使用ftp $(command_creating_ftp_URI_with_user_and_password)这样的命令。其他命令可以按照你描述的方式,使用标准输入流传递参数。但是有一个问题,你可以使用ps -auxww命令列出所有正在运行的命令及其参数。这样密码就会被显示出来。请查看手册,了解如何将凭据存储到外部文件中。这是可行的。或者你可以使用Python编写脚本,在互联网上有很多示例。参考https://dev59.com/P4jca4cB1Zd3GeqPt0G_ - Znik
显示剩余2条评论
2个回答

7

我使用:

ftp -v -n >> /tmp/ftpb.log <<EOF
        open $URL
        user $USER $PASS
        binary
        put $FILE
        quit
EOF

并且工作正常


如果您认为“-n”是关键,请在您的答案中明确说明。 - Martin Prikryl
“-n”标志不幸地无法工作,我已经尝试过了。现在我正在使用“scp”,因为它可以正常工作。 - steff

0

通常使用类似这样的内容:

$: ftp -vn <<!
> open localhost
> user foo
> put someFile
> quit
> !
> ftp: connect :Connection refused
Not connected.
Not connected.
Not connected.
$: echo $?
0

很不幸,FTP 认为它已经成功报告了所有问题,因此以零的状态退出。

使用 scp

if scp "$lcldir/$filename" "$usr/$pw@$svr:$dir/"
then echo "file delivered"
else echo "delivery failed"
fi

如果你无法使用scp,可以尝试使用类似expect的工具,或者用Perl编写一些交互式测试代码以确认每个步骤。

作为最后的手段,可以使用here-doc将文件发送并拉回到本地不存在的临时文件中。如果之后可以成功运行cmp file1 file2,则说明发送已经成功。


在最后,你应该使用grep/sed命令,并根据结果做出决定,判断是否找到了成功的字符串。请注意,在sh和bash中,$?代表管道中最后一个命令的退出状态。根据这个例子,你可以使用过滤器|grep '^Not connected'来筛选出需要的内容。如果找到了该字符串,退出代码将为0,表示传输失败。 - Znik
有时候这就是你所需要的,所以这是一个很好的观点。但有时候并不是这样,正如我在这里这里这里以及其他一些地方所提到的。因人而异。找出你的需求,进行充分测试,并选择最简单、最稳定的选项。对我来说,几乎总是使用scp,尤其是如果你可以使用可信任的连接而不必担心密码问题。即使如此,我可能更喜欢使用expect而不是通用的ftp,但每个人都有自己的偏好。 - Paul Hodges
1
考虑使用curl命令进行FTP或其他协议文件传输。 - Znik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接