web-dev-qa-db-ja.com

シェルスクリプトでwgetおよびその他のコマンドを実行する

最新のAtomic gotrootルールをサーバーにダウンロードし、それらを解凍し、正しいフォルダーにコピーするなどのシェルスクリプトを作成しようとしています。

私は一日中、シェルのチュートリアルとフォーラムの投稿を読んでいますが、これらの構文を使用すると、構文がエスケープされます。私はこれらすべてのコマンドを実行しましたが、手動で実行すると機能することはわかっています。

エラーチェックを開発する必要があることはわかっていますが、コマンドを正しく実行しようとしています。現時点での主な問題は、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
7
jimlongo

シェルスクリプトを作成するときに使用するいくつかのガイドラインを次に示します。

  1. 変数を使用するときは常に変数を引用してください。これにより、誤解の可能性を回避できます。 (ファイル名にスペースが含まれている場合はどうなりますか?)
  2. rmのようなコマンドのfileglobbingを信頼しないでください。代わりにforループを使用してください。 (ファイル名がハイフンで始まる場合はどうなりますか?)
  3. 可能な場合はサブシェルを避けてください。バッククォート付きの行は私をかゆくします。
  4. あなたがそれを助けることができるなら、実行しないでください。そして、特にスクリプトのどの部分も期待しないでくださいexecの後が実際に実行されるようにします。

あなたのシェルは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

これをより賢明なものに書き直しましたが、確かにまだ改善の余地がたくさんあることに注意してください。

10
ghoti

次の2つのオプションがあります。

1-これを

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

次に実行します

wget $WGET1 WGET2と同じ

または

2- $ WGET1をバッククォート ``でカプセル化します。例えば。:

`$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
1
Ahmed Jolani