Есть Вордпресс установки для Debian


Я написал следующий скрипт на bash, который включает в себя сервер Nginx на WordPress загрузчик: программа создания быстрых приложений для wordpress на Debian, nginx и окружающей среды.

Он использует CertBot для HTTPS, по sshguard для защиты от БФА (см. nginx в конф), то WP-CLI для создания WP приложение реж и conf файлов, в MySQL CLI для создания dbstack и местные функции rse чтобы перезапустить сервер и давать соответствующие разрешения в приложение реж.

#!/bin/bash
domain="$1" && test -z "$domain" && exit 2

environment() {
    read -sp "Please enter the app DB root password:      " dbrootp_1 && echo
    read -sp "Please enter the app DB root password again:" dbrootp_2 && echo
    if [ "$dbrootp_1" != "$dbrootp_2" ]; then echo "Values unmatched. Please try again." && exit 2 fi

    read -sp "Please enter the app DB user password:      " dbuserp_1 && echo
    read -sp "Please enter the app DB user password again:" dbuserp_2 && echo
    if [ "$dbuserp_1" != "$dbuserp_2" ]; then echo "Values unmatched. Please try again." && exit 2 fi
}
environment

wordpress() {
    rm -rf "$drt"/"$domain"/ 2>/dev/null
    wp core download --path="$drt"/"$domain"/ --allow-root
    wp config create --path="$drt"/"$domain"/ --dbname="$domain" --dbuser="$domain" --dbpass="$dbuserp" --dbhost="localhost" --allow-root
}
wordpress

nginx() {
    rm "$s_a/$domain.conf" 2>/dev/null
    rm "$s_e/$domain.conf" 2>/dev/null

    cat <<-EOF > "$s_a/$domain.conf"
        server {
            root ${drt}/${domain}/;
            server_name ${domain} www.${domain};
            location ~* \.(jpg|jpeg|png|gif|ico|css|js|ttf|woff|pdf)$ {expires 365d;}
            location "/wp-login\.php" {access_log "/var/log/httpd/wordpress-logins.log";}
        }
    EOF

    ln -sf "$s_a"/"$domain".conf "$s_e"
    rse
}
nginx

certbot() {
    certbot --nginx -d "$domain" -d www."$domain"
    rse
}
certbot

database() {
    cat <<-EOF | mysql -u root -p"$dbrootp_1"
        DROP USER IF EXISTS "$domain"@"localhost";
        DROP database IF EXISTS "$domain";
        CREATE USER "$domain"@"localhost" IDENTIFIED BY "$dbuserp_1";
        CREATE DATABASE "$domain";
        GRANT ALL PRIVILEGES ON "$domain".* TO "$domain"@"localhost";
    EOF
}
database

finalize() {
    echo "Change http to http2 in your Nginx app conf and run rse"
}
finalize

Примечание

Перед выполнением скрипта заявил в конце $HOME/.bashrc:

drt="/var/www/html"
s_a="etc/nginx/sites-available"
s_e="etc/nginx/sites-enabled"


146
2
задан 3 марта 2018 в 01:03 Источник Поделиться
Комментарии
2 ответа

Мой ответ собирается сосредоточиться на использовании функции Shell и глобальные переменные. Нет никаких фактических синтаксических ошибок в скрипте AFAICT, но неправильное использование функций в этом скрипте-это опасно ошибок.

Есть две основные причины для использования функции в bash (или любой язык, на самом деле).

Первый заключается в параметризации часто выполняемых операций - например, передавая аргументы, а не жесткого кодирования значений (или, опираясь на побочные эффекты). При необходимости она должна возвращать результат клиенту (в скорлупе, печатая что-то на stdout, чтобы быть захвачены с подстановкой команд. Или иногда путем изменения переменной в окружающей среде - см. ниже об этом)

Ты не делаешь этого.

Хуже, вы делаете свои функции полагаться на глобальные переменные. Это делает ваши функции (и скрипты) зависит от побочных эффектов предыдущих определений переменных, которые могут до сих пор держат старые значения из предыдущих прогонов (и вы забыли обновить их для текущего прогона) или, что еще хуже, может быть пустым, потому что они не были инициализированы, но в текущей оболочке. Это неизбежно приведет к катастрофической потери данных в один прекрасный день, когда вы забыли установить значение "$ДРТ" и/или "$Domain" и/или многие другие глобальные переменные.

Лучше для передачи значений в качестве параметров, когда и как нужно. Не верю, что важнейшей переменной случайно были заданы какое-то время в прошлом, т. е. быть явным, а не подразумеваемым.

Как правило, функции должны быть самодостаточной и не полагаться на переменные, которые могут или не могут быть определены за пределами их области. Они также должны определить переменные как локальные их настолько, что они явно не используют (или, что еще хуже, изменить) глобальной переменной, которая происходит с одинаковым именем переменной.

В любом случае, как wordpress функция может быть написана:

wordpress() {
local drt="$1"
local domain="$2"
local dbpass="$3"

# should do more checking here, this is the bare minimum.
# it avoids running `rm -rf /` if both $drt and $domain
# are empty, and running `rm -rf "$drt/"` if $domain is empty.
[ -z "$drt" ] && error 1 '$drt is empty. aborting!'
[ -z "$domain" ] && error 1 '$domain is empty. aborting!'
[ -z "$dbpass" ] && error 1 '$dbpass is empty. aborting!'

# should check exit status of each command run here and take
# appropriate action on any failures. Figure out what you want
# to happen if any of the following fail and implement it.
rm -rf "$drt"/"$domain"/ 2>/dev/null
wp core download --path="$drt"/"$domain"/ --allow-root
wp config create --path="$drt"/"$domain"/ --dbname="$domain" \
--dbuser="$domain" --dbpass="$dbpass" --dbhost=localhost \
--allow-root
}

Вы бы назвали это как wordpress "$drt" "$domain" "$dbpass". Он использует функцию, называемую error:

error() {
local ec msg

ec="$1" ; shift
msg="$*"

[ -n "$msg" ] && echo "$msg" >&2
# don't exit if $ec==0 - just return after printing a warning to stderr
[ "$ec" != 0 ] && exit "$ec"
}

Вторая причина заключается в том , чтобы сделать структуру сценария легче следовать. Например, вместо того, большое шелл-кода для каждой модели подобраны в случае заявление (что делает его трудно сразу увидеть, какие случаи бывают и что каждый из них делает), написать функцию для каждого случая и называют его - с или без аргументов.

Вы не делаете что либо - вы используете каждую функцию, как только вы определяете его. Это так странно и бессмысленно....особенно так, так как свои функции не принимают аргументов.

Более обычным способом определения и использования функций будет что-то вроде:

function1 () { ... ; }
function2 () { ... ; }
function3 () { ... ; }
function4 () { ... ; }

main () {
function1
function2
function3
function4
}

main

Примечание: использованиеmain функция позволяет определить и вызов функции в любом порядке, и позволяет определить свои функции (кроме main() сама) в конце скрипта, так что основной код идет первым. В противном случае вы можете сделать ошибки в тех ситуациях, когда, например, ваш основной функции код скрипта функция2, прежде чем он определяется.

как отмечалось выше, каждый вызов функции может, или должна, иметь явные аргументы, передав значения, которые они будут использовать.

Кстати, для case заявление, упомянутых выше:

case "$var" in
1) function1 ;;
2) function2 ;;
3) function3 ;;
4) function4 ;;
*) error 1 'Unknown case' ;;
esac

Это заявление дело будет намного сложнее читать, если каждый случай 5 или 10 или больше строчек кода.

2
ответ дан 3 марта 2018 в 03:03 Источник Поделиться

@КАС уже указали на самые важные проблемы.
Я добавить несколько мелких точек на вершине, что.

Синтаксические ошибки

Отсутствует точка с запятой перед fi на этой линии и другую аналогичную строку:


if [ "$dbrootp_1" != "$dbrootp_2" ]; then echo "Values unmatched. Please try again." && exit 2 fi

Юзабилити

Сценарий не очень удобные.
Например,
если введенные пароли не совпадают,
он печатает "пожалуйста, попробуйте снова", и выходит.
Я ожидаю, что "попробуйте еще раз" означает, что я могу ввести пароль еще раз, а не то, что я должен снова запустить скрипт еще раз.
Если я случайно неправильно ввел 2-й пароль для пользователя БД,
и я вынужден повторно вводить слишком корневой пароли ДБ,
Я буду очень недоволен сценарием.

А также рассол с этой строки:


read -sp "Please enter the app DB root password:      " dbrootp_1 && echo

Как пользователь, я нахожу много заготовок после : странно. Я хотел найти одну пустую естественно.

Не повторяйся

Ввод БД root и пароль пользователя БД очень похожи,
и хороший кандидат для параметризации и распакуйте в отдельную функцию.

Что-то вроде этого (спасибо @КАС для > /dev/tty совет):

readpw() {
local pw1 pw2 label=$1
while :; do
read -sp "Please enter the $label password: " pw1 && echo
read -sp "Please enter the $label password again: " pw2 && echo
[ "$pw1" = "$pw2" ] && break
echo "The values don't match. Please try again."
done > /dev/tty
echo "$pw1"
}

dbuserpw=$(readpw "app DB user")
dbrootpw=$(readpw "app DB root")

Обратите внимание, что стоимость $(...) все, что было написано на stdoutминус конечные символы новой строки. В > /dev/tty чтобы предотвратить выход на stdout что мы не хотим захвата $(...) (спасибо @КАС!).

2
ответ дан 7 марта 2018 в 06:03 Источник Поделиться