通过 SSH 的 Bash 脚本中的“:”字符出现问题

通过 SSH 的 Bash 脚本中的“:”字符出现问题

我目前正在编写一个脚本,它将对一组数据库执行备份,压缩它们,加密它们,将它们传输到单独的存储计算机,并验证文件是否成功。我可以创建备份并执行标准压缩和加密,以便可以安全地传输并存储在辅助位置。此后,ssh用于验证目标计算机上是否存在目录或强制创建该目录,然后用于scp传输文件,最后ssh用于验证另一端是否存在该文件。

这在过去效果很好,但是对脚本进行了更改,以在文件名中包含时间戳(除了现有的日期戳),并且:文件名中该时间戳中的字符导致传输在传输scp和下面ssh来测试该文件的存在。

DATE目前,我正在脚本顶部创建一个变量并将其设置为以下内容: $(date --date=today +%FT%H:%M:%S%z),这会在正确的位置生成日期戳ISO 8601格式。这可以很好地创建数据库转储(使用 创建的 postgres 转储pg_dump)以及使用压缩gzip和加密openssl。其中每一个都会生成一个新文件,所有名称的格式为HOSTNAME.DATABASE-dump-DATE.EXTENSION.

当向文件名提供日期而没有时间,因此没有字符时:,它工作得很好。我现在收到的具体错误是有:字符的以下代码段($1指提供给脚本的参数,包含要备份的数据库的名称,$DATE是上面定义的):

scp -P PORT "$(hostname).$1-dump-$DATE.backup.gz.aes" USER@HOST:"/backups/$(hostname)/"

此操作失败并出现错误ssh: could not resolve hostname HOSTNAME.DATABASE-dump-2015-07-31T13: Name or service not known

ssh HOST -p PORT <<"HERE"
if test -f /backups/$(hostname)/$(hostname).$1-dump-$DATE.backup.gz.aes;
then echo "File exists";
else echo "Transfer failed";
fi
HERE

这失败了Pseudo-terminal will not be allocated because stdin is not a terminal。使用-t会产生相同的错误,并且使用-t -t(来自在堆栈溢出导致关于伪终端的兔子洞)不允许之后给出的命令流过,这可能是我错过的关于它实际作用的事情。

我想避免使用需要在计算机上安装的任何其他软件(运行 Ubuntu 14.04 和最新的 Postgresql for DB)。请告诉我是否有任何方法scp/ssh可以正确处理这些文件。

答案1

scp -P PORT "$(hostname).$1-dump-$DATE.backup.gz.aes" USER@HOST:"/backups/$(hostname)/"

scp 支持将文件从一台远程主机复制到另一台远程主机,执行此操作的语法是使用“主机名:文件名”语法指定源和目标:

scp srchost:/src/file desthost:/dest/file

您的源文件名称中包含冒号,因此 scp 尝试将其解析为远程文件的主机名和文件名。

您可以通过确保参数的第一个冒号之前有一个“/”来防止 scp 将源文件名参数视为远程文件名。主机名中不能包含“/”,并且 scp 在第一个“/”之后停止在命令行参数中查找冒号。这应该有效:

scp -P PORT "./$(hostname).$1-dump-$DATE.backup.gz.aes" USER@HOST:"/backups/$(hostname)/"
             ^^-- Prepend a ref to the current directory

相关内容