简体   繁体   English

备份bash脚本的第一个参数

[英]Backup the first argument on bash script

I wrote a script to backup the first argument that the user input with the script: 我编写了一个脚本来备份用户使用脚本输入的第一个参数:

#!/bin/bash
file=$1/$(date +"_%Y-%m-%d").tar.gz
if [ $1 -eq 0 ]
then
    echo "We need first argument to backup"
else
    if [ ! -e "$file" ]; then
        tar -zcvf $1/$(date +"_%Y-%m-%d").tar.gz $1
    else 
        exit 
    fi
fi 

The result that i want from the script is 我想要的脚本结果是

  1. backup folder the first argument that user input 备份文件夹用户输入的第一个参数
  2. save the backup file into folder that user input with date time format. 将备份文件保存到用户以日期时间格式输入的文件夹中。

but the script is not running when I try to input the argument. 但是当我尝试输入参数时脚本未运行。 What's wrong with the script? 脚本出了什么问题?

The backup part of your script seem to be working well, but not the part where you check that $1 is not empty. 脚本的备份部分似乎运行良好,但不能检查$1是否为空。

Firstly you would need quotes around $1 , to prevent that it expends to nothing. 首先,您需要在$1左右$1引号,以防止其花费为零。 Without the quotes the shell sees it as 没有引号,shell会将其视为

if [ -eq 0 ]

and throws an error. 并引发错误。

Secondly it would be better to use the -z operator to test if the variable exists: 其次,最好使用-z运算符来测试变量是否存在:

if [ -z "$1" ]

Now you script should work as expected 现在您的脚本应该可以按预期工作

I see several problems: 我看到几个问题:

  • As H. Gourlé pointed out, the test for whether an argument was passed is wrong. 正如H.Gourlé所指出的那样,检验是否通过参数的测试是错误的。 Use if [ -z "$1" ] to check for a missing/blank argument. if [ -z "$1" ]用于检查参数是否缺失。
  • Also, it's almost always a good idea to wrap variable references in double-quotes, as in "$1" above. 另外,将变量引用用双引号引起来几乎总是一个好主意,例如上面的"$1" You do this in the test for whether $file exists, but not in the tar command. 您可以在测试中检查$file是否存在,但在tar命令中不这样做。 There are places where it's safe to leave the double-quotes off, but the rules are complicated; 在某些地方可以安全地取消双引号,但是规则很复杂; it's easier to just always double-quote. 总是总是双引号会更容易。
  • In addition to checking whether $1 was passed, I'd recommend checking whether it corresponds to a directory (or possibly file) that actually exists. 除了检查是否传递了$1 ,我还建议检查它是否对应于实际存在的目录(或可能是文件)。 Use something like: 使用类似:

     if [ -z "$1" ]; then echo "$0: We need first argument to backup" >&2 elif [ ! -d "$1" ]; then echo "$0: backup source $1 not found or is not a directory" >&2 

    BTW, note how the error messages start with $0 (the name the script was run as) and are directed to error output (the >&2 part)? 顺便说一句,请注意错误消息如何以$0开头(运行脚本的名称)并定向到错误输出( >&2部分)? These are both standard conventions for error messages. 这些都是错误消息的标准约定。

  • This isn't serious, but it really bugs me: you calculate $1/$(date +"_%Y-%m-%d").tar.gz , store it in the file variable, test to see whether something by that name exists, and then calculate it again when creating the backup file. 这并不严重,但这确实让我感到烦恼:您计算$1/$(date +"_%Y-%m-%d").tar.gz ,将其存储在file变量中,测试是否通过该名称存在,然后在创建备份文件时再次计算 There's no reason to do that; 没有理由这样做。 just use the file variable again. 只需再次使用file变量。 The reason it bugs me is partly that it violates the DRY ("Don't Repeat Yourself") principle, partly that if you ever change the naming convention you have to change it consistently in two places or the script will not work, and partly because in principle it's possible that the script will run just at midnight, and the first calculation will get one day and the second will get a different day. 令我感到困扰的部分原因是它违反了DRY(“不要重复自己”)原则,部分原因是,如果您曾经更改命名约定,则必须在两个地方进行一致的更改,否则脚本将无法工作,部分原因是因为原则上该脚本有可能仅在午夜运行,并且第一次计算将花费一天,而第二次计算将花费另一天。
  • Speaking of naming conventions, there's a problem with how you store the backup file. 说到命名约定,存储备份文件的方式存在问题。 If you put it in the directory that's being backed up, then the first day you'll get a .tar.gz file containing the previous contents of the directory. 如果将其放在要备份的目录中,则第一天您将获得一个.tar.gz文件,其中包含该目录的先前内容。 The second day you'll get a file containing the regular contents plus the first backup file . 第二天,您将获得一个包含常规内容的文件以及第一个备份文件 Thus, the second day's backup will be about twice as big. 因此,第二天的备份大约是原来的两倍。 The third day's backup will contain the regular contents, plus the first two backup files, so it'll be four times as big. 第三天的备份将包含常规内容以及前两个备份文件,因此它将是原来的四倍。 And the fourth day's will be eight times as big, then 16 times, then 32 times, etc. 第四天将是原来的八倍,然后是16倍,然后是32倍,依此类推。

    You need to either store the backup file somewhere outside the directory being backed up, or add something like --exclude="*.tar.gz" to the arguments to tar . 您需要将备份文件存储在要备份的目录之外的某个地方,或者在tar的参数中添加--exclude="*.tar.gz"之类的内容。 The disadvantage of the --exclude option is that it may exclude other .tar.gz files from the backup, so I'd really recommend the first option. --exclude选项的缺点是它可能会从备份中排除其他.tar.gz文件,因此,我真的建议您使用第一个选项。 And if you followed my advice about using "$file" everywhere instead of recalculating the name, you only need to make a change in one place to change where the backup goes. 而且,如果您遵循我的建议在各处使用"$file"而不是重新计算名称,则只需在一个位置进行更改即可更改备份的位置。

One final note: run your scripts through shellcheck.net . 最后一点:通过shellcheck.net运行脚本。 It'll point out a lot of common errors and bad practices before you discover them the hard way. 在用困难的方式发现它们之前,它将指出许多常见的错误和不良做法。

Here's a corrected version of the script (storing the backup in the directory, and excluding .tar.gz files; again, I recommend the other option): 这是脚本的更正版本(将备份存储在目录中,并且排除.tar.gz文件;再次,我建议另一个选择):

#!/bin/bash

file="$1/$(date +"_%Y-%m-%d").tar.gz"

if [ -z "$1" ]; then
    echo "$0: We need first argument to backup" >&2

elif [ ! -d "$1" ]; then
    echo "$0: backup source $1 not found or is not a directory" >&2

elif [ -e "$file" ]; then
    echo "$0: A backup already exists for today" >&2

else
    tar --exclude="*.tar.gz" -zcvf "$file" "$1"
fi

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM