如何在 Bash 脚本中将 (FTP) 文件上传到服务器?
Posted
技术标签:
【中文标题】如何在 Bash 脚本中将 (FTP) 文件上传到服务器?【英文标题】:How can I upload (FTP) files to server in a Bash script? 【发布时间】:2010-12-26 01:06:18 【问题描述】:我正在尝试编写一个将文件上传到服务器的 Bash 脚本。我怎样才能做到这一点?使用 Bash 脚本是否合适?
【问题讨论】:
解决方案不是针对 ftp 协议,而是针对 ssh。 【参考方案1】:以下是两个答案。首先是建议使用更安全/更灵活的解决方案,例如 ssh/scp/sftp。二是讲解如何以批处理方式运行ftp。
安全的解决方案:
您确实应该为此使用 SSH/SCP/SFTP 而不是 FTP。 SSH/SCP 的好处是更安全,并且可以使用公钥/私钥,无需用户名或密码即可运行。
您可以发送单个文件:
scp <file to upload> <username>@<hostname>:<destination path>
或整个目录:
scp -r <directory to upload> <username>@<hostname>:<destination path>
有关设置密钥和使用 RSYNC 将文件移动到服务器的更多详细信息,如果您有很多文件要移动,或者如果您有时在一组随机文件中只得到一个新文件,这很有用,请采取看看:
http://troy.jdmz.net/rsync/index.html
您也可以在 ssh 到服务器后执行单个命令:
来自man ssh
ssh [...snipped...] hostname [command] 如果指定了命令,则为 在远程主机而不是登录 shell 上执行。
所以,一个示例命令是:
ssh username@hostname.example bunzip file_just_sent.bz2
如果您可以使用带有密钥的 SFTP 来获得安全连接的好处,那么我使用了两个技巧来执行命令。
首先,您可以使用 echo 和管道传递命令
echo "put files*.xml" | sftp -p -i ~/.ssh/key_name username@hostname.example
您还可以使用带有-b
参数的批处理文件:
sftp -b batchfile.txt ~/.ssh/key_name username@hostname.example
一个 FTP 解决方案,如果你真的需要它:
如果您了解 FTP 不安全且受到更多限制,并且您真的很想编写脚本...
http://www.stratigery.com/scripting.ftp.html 上有一篇很棒的文章
#!/bin/sh
HOST='ftp.example.com'
USER='yourid'
PASSWD='yourpw'
FILE='file.txt'
ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
binary
put $FILE
quit
END_SCRIPT
exit 0
-n
到 ftp 确保命令不会尝试从当前终端获取密码。另一个花哨的部分是使用heredoc:<<END_SCRIPT
启动heredoc,然后在行首的完全相同的END_SCRIPT
单独结束heredoc。 binary
命令会将其设置为二进制模式,这有助于您传输文本文件以外的内容。
【讨论】:
我想这样做!您能否详细说明我如何做到这一点?上传文件后,我需要用 ssh 做一些事情。这可以在一个会话中完成吗? 虽然这对 OP 来说是有用的建议,但它不应该是公认的答案。它没有回答原始问题(通过 Google 找到) 其他一些发布者在 FTP 命令中添加了二进制模式(即bin
)。由于您的答案已被接受,因此我建议您也将其添加到您的答案中。
感谢您的回答,包括 ssh 和 FTP。我不明白关于 FTP 的大惊小怪。也许我正在为一个网站在 FTP 上的客户工作,我只是不在乎,我只关心客户想用他的网站做什么。
也可以输入hash
以某种方式显示ftp传输的进度。此外,您通常会在文件结尾看到 <<EOF
。【参考方案2】:
您可以使用heredoc 来执行此操作,例如
ftp -n $Server <<End-Of-Session
# -n option disables auto-logon
user anonymous "$Password"
binary
cd $Directory
put "$Filename.lsm"
put "$Filename.tar.gz"
bye
End-Of-Session
所以ftp
进程以标准输入为基础,直到End-Of-Session
。这是生成任何进程的有用提示,而不仅仅是ftp
!请注意,这样可以避免生成一个单独的进程(echo、cat 等)。这不是主要的资源节省,但值得牢记。
【讨论】:
这完全令人困惑。我如何摆脱这个会话结束的事情?为什么不直接输入到没有那个的ftp提示符呢? @erikb85 - 这用于脚本,而不是(必须)用于交互使用。 heredoc 将自动在您的“会话结束”标记上注册一个动作(您可能会使用 EOF 或类似的)【参考方案3】:ftp
命令不是为脚本设计的,所以控制它很尴尬,并且获得它的退出状态更尴尬。
Curl 是可编写脚本的,并且还有一个优点是您以后只需修改 URL 即可轻松切换到其他协议。如果您将 FTP 凭据放入您的 .netrc,您可以这样做:
# Download file
curl --netrc --remote-name ftp://ftp.example.com/file.bin
# Upload file
curl --netrc --upload-file file.bin ftp://ftp.example.com/
如果必须,您可以直接在命令行上使用--user username:password
而不是--netrc
指定用户名和密码。
【讨论】:
这是更简单的解决方案。curl
默认情况下未安装在Ubuntu MATE 20.04(Focal Fossa)上。 (但lftp 也不是。)【参考方案4】:
安装 ncftpput 和 ncftpget。它们通常是同一个包的一部分。
【讨论】:
命令行是:"ncftpput -u username -p password server.org /path/filename.blah" 注意连接不会被加密,密码会以明文形式发送。 @Adam “连接不会被加密”等是使用 FTP 的结果,这是在问题中指定的。无论您使用什么 FTP 客户端,它都会发生。【参考方案5】:一行命令:
ftp -in -u ftp://username:password@servername/path/to/ localfile
【讨论】:
@erikbwork -u is: " -u URL file [...] - 将命令行上的文件上传到 URL,其中 URL 是自动获取支持的 ftp URL 类型之一(使用单个文件上传的可选目标文件名),文件是要上传的一个或多个本地文件。” 您使用的是哪个版本的 ftp?它不适用于 ubuntu 18【参考方案6】:使用它来将文件上传到远程位置:
#!/bin/bash
#$1 is the file name
#usage:this_script <filename>
HOST='your host'
USER="your user"
PASSWD="pass"
FILE="abc.php"
REMOTEPATH='/html'
ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
cd $REMOTEPATH
put $FILE
quit
END_SCRIPT
exit 0
【讨论】:
这是不使用 .netrc 的一个相当晚的答案,但是它可以扩展删除并使我们中的许多人摆脱 wput/wget/wdel 分段违规漏洞。 请使用 USER 和 PASS 登录。 解释一下。例如,它与之前的答案有何不同?【参考方案7】:#/bin/bash
# $1 is the file name
# usage: this_script <filename>
IP_address="xx.xxx.xx.xx"
username="username"
domain=my.ftp.domain
password=password
echo "
verbose
open $IP_address
USER $username $password
put $1
bye
" | ftp -n > ftp_$$.log
【讨论】:
你的意思是 echo "..." | ftp -n | ftp_$$.log ? 目前这会写入文件 'ftp' 并且不会产生 ftp 进程 @Yossarian:只有第一个>
应该是|
@ennuikiller:等号周围有空格,这是 Bash 不喜欢的。此外,以明文形式硬编码密码也是一个坏主意。
我确定密码问题仅用于说明目的【参考方案8】:
将文件放在根目录下的工作示例...看,这很简单:
#!/bin/sh
HOST='ftp.users.qwest.net'
USER='yourid'
PASSWD='yourpw'
FILE='file.txt'
ftp -n $HOST <<END_SCRIPT
quote USER $USER
quote PASS $PASSWD
put $FILE
quit
END_SCRIPT
exit 0
【讨论】:
#!/bin/bash #$1 是文件名 #usage:this_script没有必要让事情复杂化。这应该有效:
#/bin/bash
echo "
verbose
open ftp.mydomain.net
user myusername mypassword
ascii
put textfile1
put textfile2
bin
put binaryfile1
put binaryfile2
bye
" | ftp -n > ftp_$$.log
或者如果你有很多文件,你可以使用mput...
【讨论】:
【参考方案10】:如果您想在“for”中使用它来复制最后生成的文件以进行日常备份...
j=0
var="`find /backup/path/ -name 'something*' -type f -mtime -1`"
# We have some files in $var with last day change date
for i in $var
do
j=$(( $j + 1 ))
dirname="`dirname $i`"
filename="`basename $i`"
/usr/bin/ftp -in >> /tmp/ftp.good 2>> /tmp/ftp.bad << EOF
open 123.456.789.012
user user_name passwd
bin
lcd $dirname
put $filename
quit
EOF # End of ftp
done # End of 'for' iteration
【讨论】:
【参考方案11】:echo -e "open <ftp.hostname>\nuser <username> <password>\nbinary\nmkdir New_Folder\nquit" | ftp -nv
【讨论】:
解释一下。例如,想法/要点是什么?以上是关于如何在 Bash 脚本中将 (FTP) 文件上传到服务器?的主要内容,如果未能解决你的问题,请参考以下文章
在批处理文件中将文本文件上传到FTP,该文件具有随机生成的文件名