我正在编写一个非常简单的bash脚本,其中包含一个给定的目录,对其输出进行encryption,然后将生成的文件分割成多个较小的文件,因为备份介质不支持大文件。
我没有很多有关bash脚本的经验。 我相信我有问题正确地引用我的variables,以允许参数中的空格。 脚本如下:
#! /bin/bash # This script tars the given directory,encrypts it,and transfers # it to the given directory (likely a USB key). if [ $# -ne 2 ] then echo "Usage: `basename $0` DIRECTORY BACKUP_DIRECTORY" exit 1 fi DIRECTORY=$1 BACKUP_DIRECTORY=$2 BACKUP_FILE="$BACKUP_DIRECTORY/`date +%Y-%m-%dT%H-%M-%s.backup`" TAR_CMD="tar cv $DIRECTORY" SPLIT_CMD="split -b 1024m - "$BACKUP_FILE"" ENCRYPT_CMD='openssl des3 -salt' echo "$TAR_CMD | $ENCRYPT_CMD | $SPLIT_CMD" $TAR_CMD | $ENCRYPT_CMD | $SPLIT_CMD say "Done backing up"
运行此命令失败:
分割:“foo / 2009-04-27T14-32-04.backup”aa:没有这样的文件或目录
我如何在Linux上pipe理基于Python的守护进程?
Bash:我如何截断一个数组?
分析shell脚本参数
使用date命令打印上个月的最后一个date
我可以通过删除$BACKUP_FILE附近的引号来解决这个$BACKUP_FILE ,我设置了$SPLIT_CMD 。 但是,如果我有我的备份目录的名称空间不起作用。 另外,如果我将“echo”命令的输出直接复制并粘贴到terminal中,则工作正常。 显然,我不明白Bash是如何逃离事物的。
Linux:对于“tail -f文件名”,只能在 n后面读取行吗?
如何wget更新的目录文件
最后运行不同的选项GNU并行
为什么在python中inputunicode字符-c抛出exception
Cronjob不运行bash脚本
不要把整个命令放在变量中。 尝试恢复引用的参数会遇到很多麻烦。
也:
避免在脚本中使用全部大写的变量名称。 简单的方法来拍摄自己的脚。
不要使用反引号,而是使用$(…),它的嵌套效果更好。
#! /bin/bash if [ $# -ne 2 ] then echo "Usage: $(basename $0) DIRECTORY BACKUP_DIRECTORY" exit 1 fi directory=$1 backup_directory=$2 current_date=$(date +%Y-%m-%dT%H-%M-%s) backup_file="${backup_directory}/${current_date}.backup" tar cv "$directory" | openssl des3 -salt | split -b 1024m - "$backup_file"
我不确定,但是可能首先在命令上运行eval。
这可以让bash扩展变量$ TAR_CMD等等,使其达到完全的宽度(就像echo命令对控制台所做的那样)
然后,Bash将会在变量扩展后再次读取该行。
eval $TAR_CMD | $ENCRYPT_CMD | $SPLIT_CMD
我只是做了一个谷歌搜索,这个页面看起来像是可以做一个体面的工作来解释为什么这是必要的。 http://fvue.nl/wiki/Bash:_Why_use_eval_with_variable_expansion%3F
如果您的目录名称可以由不受信任的来源生成eval是不可接受的做法。 有关更多关于为什么不使用eval更多信息,请参阅BashFAQ#48 ,关于此问题的根本原因及其正确的解决方案,请参阅BashFAQ# 50以获得更多信息。
如果你需要随着时间的推移建立你的命令,使用数组:
tar_cmd=( tar cv "$directory" ) split_cmd=( split -b 1024m - "$backup_file" ) encrypt_cmd=( openssl des3 -salt ) "${tar_cmd[@]}" | "${encrypt_cmd[@]}" | "${split_cmd[@]}"
tar_cmd() { tar cv "$directory"; } split_cmd() { split -b 1024m - "$backup_file"; } encrypt_cmd() { openssl des3 -salt; } tar_cmd | split_cmd | encrypt_cmd
只有把命令和选项放在变量中才有意义。
#! /bin/bash if [ $# -ne 2 ] then echo "Usage: `basename $0` DIRECTORY BACKUP_DIRECTORY" exit 1 fi . standard_tools directory=$1 backup_directory=$2 current_date=$(date +%Y-%m-%dT%H-%M-%s) backup_file="${backup_directory}/${current_date}.backup" ${tar_create} "${directory}" | ${openssl} | ${split_1024} "$backup_file"
您可以将这些命令重定位到另一个源文件,以便可以在多个脚本中重复使用相同的命令和选项。 当你有很多的脚本,你想控制他们如何使用工具,这是非常方便的。 所以standard_tools将包含:
export tar_create="tar cv" export openssl="openssl des3 -salt" export split_1024="split -b 1024m -"
引用变量中的空格以使shell能够正确地重新解释事物是很困难的 。 正是这种类型的东西促使我接触到更强大的语言。 无论是perl,python还是ruby,或者其他的(我选择perl,但并不总是适用于每个人),这只是让你绕过shell来引用。
这并不是说我从来没有用自由主义的评估方法来正确地做出正确的评估,但是正是这个评估给了我eebie-jeebies(当你想要用户输入并评估它时,会变成一个全新的头痛,尽管在这种情况下,你会采取你写的东西,而不是),而我已经在调试中头痛。
用perl,就像我的例子一样,我可以做一些事情:
@tar_cmd = ( qw(tar cv),$directory ); @encrypt_cmd = ( qw(openssl des3 -salt) ); @split_cmd = ( qw(split -b 1024m -),$backup_file );
这里最困难的部分是做管道 – 但有一点IO :: Pipe ,fork,重新打开stdout和stderr,这并不坏。 有人会说这比引用shell更糟,而且我明白他们来自哪里,但是对于我来说,读取,维护和写入更容易。 哎呀,有人可以从这个辛苦的工作,并创建一个IO ::管道模块,使整个事情微不足道;-)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。