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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19965228/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:25:40  来源:igfitidea点击:

Run wget and other commands in shell script

bashshellwget

提问by jimlongo

I'm trying to create a shell script that I will download the latest Atomic gotroot rules to my server, unpack them, copy them to the correct folder, etc.,

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

I've been reading shell tutorials and forum posts for most of the day and the syntax escapes me for some of these. I have run all these commands and I know they work if I manually run them.

我一天中的大部分时间都在阅读 shell 教程和论坛帖子,其中一些语法让我无法理解。我已经运行了所有这些命令,如果我手动运行它们,我知道它们可以工作。

I know I need to develop some error checking, but I'm just trying to get the commands to run correctly. The main problem at the moment is the syntax of the wget commands, i've got errors about missing semi-colons, divide by zero, unsupported schemes - I've tried various quoting (single and double) and escaping - / " characters in various combinations.

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

Thanks for any help. The raw wget command is

谢谢你的帮助。原始 wget 命令是

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

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

回答by ghoti

Here are some guidelines to use when writing shell scripts.

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

  1. Always quote variables when you use them. This helps avoid the possibility of misinterpretation. (What if a filename contains a space?)
  2. Don't trust fileglobbing on commands like rm. Use forloops instead. (What if a filename starts with a hyphen?)
  3. Avoid subshells when possible. Your lines with backquotes make me itchy.
  4. Don't exec if you can help it. And especially don't expect any parts of your script after your execto actually get run.
  1. 使用变量时总是引用变量。这有助于避免误解的可能性。(如果文件名包含空格怎么办?)
  2. 不要相信 fileglobbing 之类的命令rm。改用for循环。(如果文件名以连字符开头怎么办?)
  3. 尽可能避免使用子shell。你带反引号的台词让我很痒。
  4. 如果你能帮上忙,就不要执行。尤其不要指望您的 exec实际运行脚本的任何部分。

I should point out that while your shell may be bash, you've specified /bin/shfor execution of this script, so it is NOT a bash script.

我应该指出,虽然您的 shell 可能是 bash,但您已指定/bin/sh执行此脚本,因此它不是 bash 脚本。

Here's a rewrite with some error checking. Add salt to taste.

这是带有一些错误检查的重写。加盐调味。

#!/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

Note that while I've rewritten this to be more sensible, there is certainly still a lot of room for improvement.

请注意,虽然我已将其重写为更合理,但肯定仍有很大的改进空间。

回答by Ahmed Jolani

You have two options:

您有两个选择:

1- changing this to

1-将其更改为

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

then run

然后运行

wget $WGET1same to WGET2

wget $WGET1与 WGET2 相同

Or

或者

2- encapsulating $WGET1 with backquotes ``. e.g.:

2- 用反引号 `` 封装 $WGET1。例如:

`$WGET`

This applies to any command your executing out of a variable.

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

Suggested changes:

建议更改:

#!/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' $*;

Pro Tip: If you need string substitution, using ${VAR} is much better to eliminate ambiguity, e.g.:

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

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