在shell脚本中运行wget和其他命令

时间:2013-11-13 21:57:26

标签: bash shell wget

我正在尝试创建一个shell脚本,我将最新的Atomic gotroot规则下载到我的服务器,解压缩,将它们复制到正确的文件夹等,

我一直在大部分时间都在阅读shell教程和论坛帖子,语法让我对其中的一些事情感到震惊。我已经运行了所有这些命令,如果我手动运行它们,我知道它们有效。

我知道我需要开发一些错误检查,但我只是想让命令正确运行。目前的主要问题是wget命令的语法,我有关于缺少分号的错误,除以零,不支持的方案 - 我尝试了各种引用(单和双)和转义 - /“字符各种组合。

感谢您的帮助。 原始wget命令是

wget --user="jim" --password="xxx-yyy-zzz" "http://updates.atomicorp.com/channels/rules/subscription/VERSION"

#!/bin/sh
update_modsec_rules(){

wget=/usr/bin/wget
tar=/bin/tar
apachectl=/usr/bin/apache2ctl


TXT="Script Run Finished"
WORKING_DIR="/var/asl/updates"
TARGET_DIR="/usr/local/apache/conf/modsec_rules/"
EXISTING_FILES="/var/asl/updates/modsec/*"
EXISTING_ARCH="/var/asl/updates/modsec-*"
WGET_OPTS='--user=jim --password=xxx-yyy-zzz'
URL_BASE="http://updates.atomicorp.com/channels/rules/subscription"


# change to working directory and cleanup any downloaded files and extracted rules in modsec/ directory
cd $WORKING_DIR
rm -f $EXISTING_ARCH
rm -f $EXISTING_FILES
rm -f VERSION*

# wget to download VERSION file
$wget ${WGET_OPTS} "${URL_BASE}/VERSION"

# get current MODSEC_VERSION from VERSION file and save as variable
source VERSION
TARGET_DATE=$MODSEC_VERSION
echo $TARGET_DATE

# wget to download current archive
$wget ${WGET_OPTS} "${URL_BASE}/modsec-${TARGET_DATE}.tar.gz"

# extract archive
echo "extracting files . . . "
tar zxvf $WORKING_DIR/modsec-${TARGET_DATE}.tar.gz

echo "copying files . . . "
cp -uv $EXISTING_FILES $TARGET_DIR

echo $TXT
}

update_modsec_rules $@ 2>&1 | tee -a /var/asl/modsec_update.log

RESTART_APACHE="/usr/local/cpanel/scripts/restartsrv httpd"
$RESTART_APACHE

2 个答案:

答案 0 :(得分:10)

以下是编写shell脚本时要使用的一些准则。

  1. 使用时始终引用变量。这有助于避免误解的可能性。 (如果文件名包含空格怎么办?)
  2. 不信任像rm这样的命令上的文件加载。请改用for循环。 (如果文件名以连字符开头怎么办?)
  3. 尽可能避免使用子弹。带反引号的线条会让我发痒。
  4. 如果你能提供帮助,请不要执行。特别是在你的exec 实际运行之后,不要指望你的脚本的任何部分
  5. 我应该指出,虽然你的shell可能是bash,但你已经指定/bin/sh来执行这个脚本,所以它不是一个bash脚本。

    这是一个重写错误检查。加盐调味。

    #!/bin/sh
    
    # Linux
    wget=/usr/bin/wget
    tar=/bin/tar
    apachectl=/usr/sbin/apache2ctl
    
    # FreeBSD
    #wget=/usr/local/bin/wget
    #tar=/usr/bin/tar
    #apachectl=/usr/local/sbin/apachectl
    
    TXT="GOT TO THE END, YEAH"
    WORKING_DIR="/var/asl/updates"
    TARGET_DIR="/usr/local/apache/conf/modsec_rules/"
    EXISTING_FILES_DIR="/var/asl/updates/modsec/"
    EXISTING_ARCH="/var/asl/updates/"
    
    URL_BASE="http://updates.atomicorp.com/channels/rules/subscription"
    WGET_OPTS='--user="jim" --password="xxx-yyy-zzz"'
    
    if [ ! -x "$wget" ]; then
      echo "ERROR: No wget." >&2
      exit 1
    elif [ ! -x "$apachectl" ]; then
      echo "ERROR: No apachectl." >&2
      exit 1
    elif [ ! -x "$tar" ]; then
      echo "ERROR: Not in Kansas anymore, Toto." >&2
      exit 1
    fi
    
    # change to working directory and cleanup any downloaded files
    # and extracted rules in modsec/ directory
    if ! cd "$WORKING_DIR"; then
      echo "ERROR: can't access working directory ($WORKING_DIR)" >&2
      exit 1
    fi
    
    # Delete each file in a loop.
    for file in "$EXISTING_FILES_DIR"/* "$EXISTING_ARCH_DIR"/modsec-*; do
      rm -f "$file"
    done
    
    # Move old VERSION out of the way.
    mv VERSION VERSION-$$
    
    # wget1 to download VERSION file (replaces WGET1)
    if ! $wget $WGET_OPTS $URL_BASE}/VERSION; then
      echo "ERROR: can't get VERSION" >&2
      mv VERSION-$$ VERSION
      exit 1
    fi
    
    # get current MODSEC_VERSION from VERSION file and save as variable,
    # but DON'T blindly trust and run scripts from an external source.
    if grep -q '^MODSEC_VERSION=' VERSION; then
      TARGET_DATE="`sed -ne '/^MODSEC_VERSION=/{s/^[^=]*=//p;q;}' VERSION`"
      echo "Target date: $TARGET_DATE"
    fi
    
    # Download current archive (replaces WGET2)
    if ! $wget ${WGET_OPTS} "${URL_BASE}/modsec-$TARGET_DATE.tar.gz"; then
      echo "ERROR: can't get archive" >&2
      mv VERSION-$$ VERSION         # Do this, don't do this, I don't know your needs.
      exit 1
    fi
    
    # extract archive
    if [ ! -f "$WORKING_DIR/modsec-${TARGET_DATE}.tar.gz" ]; then
      echo "ERROR: I'm confused, where's my archive?" >&2
      mv VERSION-$$ VERSION         # Do this, don't do this, I don't know your needs.
      exit 1
    fi
    tar zxvf "$WORKING_DIR/modsec-${TARGET_DATE}.tar.gz"
    
    for file in "$EXISTING_FILES_DIR"/*; do
      cp "$file" "$TARGET_DIR/"
    done
    
    # So far so good, so let's restart apache.
    if $apachectl configtest; then
      if $apachectl restart; then
        # Success!
        rm -f VERSION-$$
        echo "$TXT"
      else
        echo "ERROR: PANIC! Apache didn't restart.  Notify the authorities!" >&2
        exit 3
      fi
    else
      echo "ERROR: Apache configs are broken.  We're still running, but you'd better fix this ASAP." >&2
      exit 2
    fi
    

    请注意,虽然我已经将其重写为更明智,但仍然有很大的改进空间。

答案 1 :(得分:1)

您有两种选择:

1-将此更改为

WGET1=' --user="jim" --password="xxx-yyy-zzz" "http://updates.atomicorp.com/channels/rules/subscription/VERSION"'

然后运行

wget $WGET1与WGET2相同

或者

2-用反引号``封装$ WGET1。 e.g:

`$WGET`

这适用于执行变量的任何命令。

建议的更改:

#!/bin/sh

TXT="GOT TO THE END, YEAH"
WORKING_DIR="/var/asl/updates"
TARGET_DIR="/usr/local/apache/conf/modsec_rules/"
EXISTING_FILES="/var/asl/updates/modsec/*"
EXISTING_ARCH="/var/asl/updates/modsec-*"
WGET1='wget --user="jim" --password="xxx-yyy-zzz" "http://updates.atomicorp.com/channels/rules/subscription/VERSION"'
WGET2='wget --user="jim" --password="xxx-yyy-zzz" "http://updates.atomicorp.com/channels/rules/subscription/modsec-$TARGET_DATE.tar.gz"'


## change to working directory and cleanup any downloaded files and extracted rules in modsec/ directory
cd $WORKING_DIR
rm -f $EXISTING_ARCH
rm -f $EXISTING_FILES

## wget1 to download VERSION file
`$WGET1`

## get current MODSEC_VERSION from VERSION file and save as variable
source VERSION
TARGET_DATE=`echo $MODSEC_VERSION`

## WGET2 command to download current archive
`$WGET2`
## extract archive
tar zxvf $WORKING_DIR/modsec-$TARGET_DATE.tar.gz

cp $EXISTING_FILES $TARGET_DIR

## restart server
exec '/usr/local/cpanel/scripts/restartsrv_httpd' $*;

专业提示:如果您需要字符串替换,使用$ {VAR}可以更好地消除歧义,例如:

tar zxvf $WORKING_DIR/modsec-${TARGET_DATE}.tar.gz