diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 7ba29375..5383a97f 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -28,6 +28,7 @@ jobs:
sed -i "s/AUTO_REMOVE=false/AUTO_REMOVE=true/g" .env
sed -i "s/FORCE_REMOVE=false/FORCE_REMOVE=true/g" .env
sed -i "s/LEMPER_ADMIN_EMAIL=\"mail@example.com\"/LEMPER_ADMIN_EMAIL=\"me@masedi.net\"/g" .env
+ sed -i "s/NGINX_INSTALLER="source"/NGINX_INSTALLER="repo"/g" .env
sed -i "s/INSTALL_PHP_LOADER=false/INSTALL_PHP_LOADER=true/g" .env
sed -i "s/PHP_LOADER=\"none\"/PHP_LOADER=\"ioncube\"/g" .env
sed -i "s/IMAGEMAGICK_INSTALLER=\"source\"/IMAGEMAGICK_INSTALLER=\"repo\"/g" .env
diff --git a/README.md b/README.md
index ed25ef69..ddbcc141 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# [L]inux [E]ngine-X [M]ariaDB [P]HP Install[ER]
-
+
@@ -14,7 +14,7 @@
-LEMPer stands for Linux, Engine-X (Nginx), MariaDB and PHP installer written in Bash script. This is just a small toolset (a bunch collection of scripts) that usually I use to deploy and manage LEMP stack on Debian/Ubuntu server. LEMPer is crafted to support wide-range PHP framework & CMS. It is available as Free Alternative to control panel such as cPanel, Plesk, CloudWays, Ploi, RunCloud, ServerPilot, etc.
+LEMPer stands for Linux, Engine-X (Nginx), MariaDB and PHP installer written in Bash script, also known as LEMP / LNMP installer. This is just a small toolset (a bunch collection of scripts) that I use to deploy and manage LEMP stack on Debian and Ubuntu server. LEMPer is crafted to support wide-range PHP framework & CMS. It is available as Free Alternative to the paid control panel such as cPanel, Plesk, CloudWays, Ploi, RunCloud, ServerPilot, etc.
## Features
@@ -27,7 +27,7 @@ LEMPer stands for Linux, Engine-X (Nginx), MariaDB and PHP installer written in
* Support HTTP/2 natively for your secure website.
* Free SSL certificates from [Let's Encrypt](https://letsencrypt.org/).
* Get an A+ grade on several SSL Security Test ([Qualys SSL Labs](https://www.ssllabs.com/ssltest/analyze.html?d=masedi.net), [ImmuniWeb](https://www.immuniweb.com/ssl/?id=bVrykFnK), and Wormly).
-* Multiple PHP versions 5.6 [EOL], 7.0 [EOL], 7.1 [EOL], 7.2 [EOL], 7.3 [SFO], 7.4, 8.0 from [Ondrej's repository](https://launchpad.net/~ondrej/+archive/ubuntu/php).
+* Multiple PHP versions 5.6 [EOL], 7.0 [EOL], 7.1 [EOL], 7.2 [EOL], 7.3 [SFO], 7.4, 8.0, 8.1 from [Ondrej's repository](https://launchpad.net/~ondrej/+archive/ubuntu/php).
* Run PHP as user who own the file (Multi-user isolation via FPM pool). Feel the faster Nginx with secure multi-user environment like a top-notch shared hosting.
* Supported PHP Framework and CMS:
* Vanilla PHP: default,
@@ -40,6 +40,7 @@ LEMPer stands for Linux, Engine-X (Nginx), MariaDB and PHP installer written in
* NoSQL database with MongoDB.
* In-memory database with Redis.
* Memory cache with Memcached.
+* FTP server with VSFTPD or Pure-FTPd.
* [Adminer](https://www.adminer.org/) web-based SQL & MongoDB database manager (PhpMyAdmin replacement).
* [phpRedisAdmin](https://github.com/erikdubbelboer/phpRedisAdmin) web-based Redis database manager.
* [phpMemcachedAdmin](https://github.com/elijaa/phpmemcachedadmin) web-based Memcached manager.
@@ -124,23 +125,23 @@ sudo lemper-cli manage --help
sudo lemper-cli help
```
-Note: Lemper CLI will automagically add a new PHP-FPM user's pool configuration if it doesn't exists. You must add the user account first.
+Note: LEMPer CLI automagically add a new PHP-FPM user's pool configuration if it doesn't exists. You must add the user account first.
### Web-based Administration
-You can access pre-installed web-based administration tools here
+You can access pre-installed web-based administration tools here.
```bash
http://YOUR_IP_ADDRESS:8082/lcp/
```
-Adminer (Web-based SQL database managemer)
+Adminer (Web-based SQL database manager)
```bash
http://YOUR_DOMAIN_NAME:8082/lcp/dbadmin
```
-TinyFileManager (Web-based file managemer)
+TinyFileManager (Web-based file manager)
```bash
http://YOUR_DOMAIN_NAME:8082/lcp/filemanager
@@ -161,7 +162,7 @@ Add your feature [request here](https://github.com/joglomedia/LEMPer/issues/new)
## Security Vulnerabilities and Bugs
-If you discover any security vulnerability or any bug within _LEMPer Stack_, please open an issue.
+If you discover any security vulnerability or any bug within _LEMPer Stack_, please open an [issue](https://github.com/joglomedia/LEMPer/issues/new).
## Contributing
@@ -204,16 +205,16 @@ Made with [contributors-img](https://contrib.rocks).
### Financial Contributors
-You can support us using any of the methods below:
+You can support development by using any of the methods below:
**[Buy Me a Bottle of Milk or a Cup of Coffee](https://paypal.me/masedi) !!**
## Licence
-LEMPer stack is open-source project licensed under the GNU GPLv3 license.
+LEMPer Stack is open-source project licensed under the GNU GPLv3 license.
## Copyright
-(c) 2014-2021 | [MasEDI.Net](https://masedi.net/)
+(c) 2014-2022 | [MasEDI.Net](https://masedi.net/)
### Enjoy LEMPer Stack ;)
diff --git a/bin/lemper-cli.sh b/bin/lemper-cli.sh
index d56747f5..3f226017 100644
--- a/bin/lemper-cli.sh
+++ b/bin/lemper-cli.sh
@@ -21,13 +21,108 @@ set -e
PROG_NAME=$(basename "$0")
PROG_VER="2.x.x"
-# May need to run this as sudo!
-if [[ "$(id -u)" -ne 0 ]]; then
- echo "This command can only be run by root."
+# Test mode.
+DRYRUN=false
+
+# Color decorator.
+RED=91
+GREEN=92
+YELLOW=93
+
+##
+# Helper Functions.
+##
+function begin_color() {
+ color="${1}"
+ echo -e -n "\e[${color}m"
+}
+
+function end_color() {
+ echo -e -n "\e[0m"
+}
+
+function echo_color() {
+ color="${1}"
+ shift
+ begin_color "${color}"
+ echo "$@"
+ end_color
+}
+
+function status() {
+ echo_color "${GREEN}" "$@"
+}
+
+function warning() {
+ echo_color "${YELLOW}" "$@"
+}
+
+function success() {
+ echo_color "${GREEN}" -n "Success: " >&2
+ echo "$@" >&2
+}
+
+function info() {
+ echo_color "${YELLOW}" -n "Info: " >&2
+ echo "$@" >&2
+}
+
+function error() {
+ echo_color "${RED}" -n "Error: " >&2
+ echo "$@" >&2
+}
+
+# Prints an error message and exits with an error code.
+function fail() {
+ error "$@"
+ #echo >&2
+ echo "For usage information, run this script with --help" >&2
exit 1
-fi
+}
+
+function echo_ok() {
+ echo_color "${GREEN}" "OK"
+}
+
+function echo_warn() {
+ echo_color "${YELLOW}" "WARN"
+}
+
+function echo_err() {
+ echo_color "${RED}" "ERROR"
+}
-# Export LEMPer stack configuration.
+# Run command.
+function run() {
+ if "${DRYRUN}"; then
+ echo_color "${YELLOW}" -n "would run "
+ echo "$@"
+ else
+ if ! "$@"; then
+ local CMDSTR="$*"
+ error "Failure running '${CMDSTR}', exiting."
+ exit 1
+ fi
+ fi
+}
+
+# Make sure only root can run this script.
+function requires_root() {
+ if [[ "$(id -u)" -ne 0 ]]; then
+ if ! hash sudo 2>/dev/null; then
+ echo "${PROG_NAME} command must be run as 'root' or with sudo."
+ exit 1
+ else
+ #echo "Switching to root user to run this script."
+ sudo -E "$0" "$@"
+ exit 0
+ fi
+ fi
+}
+
+requires_root "$@"
+
+# Export LEMPer Stack configuration.
if [[ -f "/etc/lemper/lemper.conf" ]]; then
# Clean environemnt first.
# shellcheck source=/etc/lemper/lemper.conf
@@ -39,8 +134,8 @@ if [[ -f "/etc/lemper/lemper.conf" ]]; then
# shellcheck disable=SC1091
source <(grep -v '^#' /etc/lemper/lemper.conf | grep -v '^\[' | sed -E 's|^(.+)=(.*)$|: ${\1=\2}; export \1|g')
else
- echo "LEMPer stack configuration required, but the file doesn't exist."
- echo "It should be created during installation process and placed under '/etc/lemper/lemper.conf'"
+ echo "LEMPer Stack configuration required, but the file doesn't exist."
+ echo "It should be created during installation process and placed under '/etc/lemper/lemper.conf'."
exit 1
fi
@@ -49,13 +144,13 @@ LEMPER_USERNAME=${LEMPER_USERNAME:-"lemper"}
LEMPER_PASSWORD=${LEMPER_PASSWORD:-""}
MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD:-""}
-# CLI plugins directory.
+# Set CLI plugins directory.
CLI_PLUGINS_DIR="/etc/lemper/cli-plugins"
##
# Show usage
# output to STDERR.
-#
+##
function cmd_help() {
cat <<- EOL
${PROG_NAME} ${PROG_VER}
@@ -76,19 +171,19 @@ EOL
##
# Show version.
-#
+##
function cmd_version() {
echo "${PROG_NAME} version $PROG_VER"
}
##
-# Main LEMPer CLI Wrapper
-#
+# Main LEMPer CLI Wrapper.
+##
function init_lemper_cli() {
# Check command line arguments.
if [[ -n "${1}" ]]; then
CMD="${1}"
- shift # Pass the remaining arguments to the next function.
+ shift # Pass the remaining arguments as sub-command options (parameters).
case ${CMD} in
help | -h | --help)
@@ -101,7 +196,9 @@ function init_lemper_cli() {
;;
*)
if [[ -x "${CLI_PLUGINS_DIR}/lemper-${CMD}" ]]; then
- "${CLI_PLUGINS_DIR}/lemper-${CMD}" "$@"
+ # Source the plugin executable file.
+ # shellcheck disable=SC1090
+ . "${CLI_PLUGINS_DIR}/lemper-${CMD}" "$@"
exit 0
else
echo "${PROG_NAME}: '${CMD}' is not ${PROG_NAME} command."
diff --git a/etc/logrotate.d/php5.6-fpm b/etc/logrotate.d/php5.6-fpm
new file mode 100644
index 00000000..c5d39d40
--- /dev/null
+++ b/etc/logrotate.d/php5.6-fpm
@@ -0,0 +1,13 @@
+/var/log/php5.6-fpm.log /home/*/logs/php/php5.6-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php5.6-fpm-reopenlogs ]; then
+ /usr/lib/php/php5.6-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php7.0-fpm b/etc/logrotate.d/php7.0-fpm
new file mode 100644
index 00000000..2b264fbe
--- /dev/null
+++ b/etc/logrotate.d/php7.0-fpm
@@ -0,0 +1,13 @@
+/var/log/php7.0-fpm.log /home/*/logs/php/php7.0-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php7.0-fpm-reopenlogs ]; then
+ /usr/lib/php/php7.0-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php7.1-fpm b/etc/logrotate.d/php7.1-fpm
new file mode 100644
index 00000000..647f6850
--- /dev/null
+++ b/etc/logrotate.d/php7.1-fpm
@@ -0,0 +1,13 @@
+/var/log/php7.1-fpm.log /home/*/logs/php/php7.1-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php7.1-fpm-reopenlogs ]; then
+ /usr/lib/php/php7.1-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php7.2-fpm b/etc/logrotate.d/php7.2-fpm
new file mode 100644
index 00000000..3097e5b6
--- /dev/null
+++ b/etc/logrotate.d/php7.2-fpm
@@ -0,0 +1,13 @@
+/var/log/php7.2-fpm.log /home/*/logs/php/php7.2-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php7.2-fpm-reopenlogs ]; then
+ /usr/lib/php/php7.2-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php7.3-fpm b/etc/logrotate.d/php7.3-fpm
new file mode 100644
index 00000000..e147f134
--- /dev/null
+++ b/etc/logrotate.d/php7.3-fpm
@@ -0,0 +1,13 @@
+/var/log/php7.3-fpm.log /home/*/logs/php/php7.3-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php7.3-fpm-reopenlogs ]; then
+ /usr/lib/php/php7.3-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php7.4-fpm b/etc/logrotate.d/php7.4-fpm
new file mode 100644
index 00000000..fe39a320
--- /dev/null
+++ b/etc/logrotate.d/php7.4-fpm
@@ -0,0 +1,13 @@
+/var/log/php7.4-fpm.log /home/*/logs/php/php7.4-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php7.4-fpm-reopenlogs ]; then
+ /usr/lib/php/php7.4-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php8.0-fpm b/etc/logrotate.d/php8.0-fpm
new file mode 100644
index 00000000..f1a4a884
--- /dev/null
+++ b/etc/logrotate.d/php8.0-fpm
@@ -0,0 +1,13 @@
+/var/log/php8.0-fpm.log /home/*/logs/php/php8.0-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php8.0-fpm-reopenlogs ]; then
+ /usr/lib/php/php8.0-fpm-reopenlogs;
+ fi
+ endscript
+}
\ No newline at end of file
diff --git a/etc/logrotate.d/php8.1-fpm b/etc/logrotate.d/php8.1-fpm
new file mode 100644
index 00000000..d6003549
--- /dev/null
+++ b/etc/logrotate.d/php8.1-fpm
@@ -0,0 +1,13 @@
+/var/log/php8.1-fpm.log /home/*/logs/php/php8.1-fpm.log {
+ rotate 12
+ weekly
+ missingok
+ notifempty
+ compress
+ delaycompress
+ postrotate
+ if [ -x /usr/lib/php/php8.1-fpm-reopenlogs ]; then
+ /usr/lib/php/php8.1-fpm-reopenlogs;
+ fi
+ endscript
+}
diff --git a/etc/nginx/sites-available/default b/etc/nginx/sites-available/default
index 018586aa..6dec3964 100644
--- a/etc/nginx/sites-available/default
+++ b/etc/nginx/sites-available/default
@@ -35,19 +35,15 @@ server {
auth_basic_user_file /srv/.htpasswd;
}
- location ~ \.(php|php74)$ {
+ location ~ \.php81$ {
try_files $uri =404;
-
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
-
include /etc/nginx/fastcgi_params;
include /etc/nginx/includes/fastcgi.conf;
-
# Uncomment to Enable PHP FastCGI cache.
#include /etc/nginx/includes/fastcgi_cache.conf;
-
- fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
location ~ \.php80$ {
@@ -60,6 +56,17 @@ server {
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
}
+ location ~ \.(php|php74)$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_index index.php;
+ include /etc/nginx/fastcgi_params;
+ include /etc/nginx/includes/fastcgi.conf;
+ # Uncomment to Enable PHP FastCGI cache.
+ #include /etc/nginx/includes/fastcgi_cache.conf;
+ fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ }
+
location ~ \.php73$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
@@ -111,7 +118,6 @@ server {
}
#include /etc/nginx/includes/error_pages.conf;
-
#include /etc/nginx/includes/fcgiwrap.conf;
}
@@ -143,7 +149,6 @@ server {
auth_basic "Denied";
auth_basic_user_file /srv/.htpasswd;
- # Pass the PHP scripts to FastCGI with basic auth.
location ~ \.php$ {
try_files $uri =404;
@@ -156,25 +161,18 @@ server {
# Uncomment to Enable PHP FastCGI cache.
#include /etc/nginx/includes/fastcgi_cache.conf;
- fastcgi_pass unix:/run/php/php7.3-fpm.sock;
+ fastcgi_pass unix:/run/php/php7.4-fpm.sock;
}
}
- # Pass the PHP scripts to FastCGI server listening on Unix socket.
- #
- location ~ \.(php|php74)$ {
+ location ~ \.php81$ {
try_files $uri =404;
-
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
-
include /etc/nginx/fastcgi_params;
include /etc/nginx/includes/fastcgi.conf;
-
- # Uncomment to Enable PHP FastCGI cache.
#include /etc/nginx/includes/fastcgi_cache.conf;
-
- fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}
location ~ \.php80$ {
@@ -187,6 +185,16 @@ server {
fastcgi_pass unix:/run/php/php8.0-fpm.sock;
}
+ location ~ \.(php|php74)$ {
+ try_files $uri =404;
+ fastcgi_split_path_info ^(.+\.php)(/.+)$;
+ fastcgi_index index.php;
+ include /etc/nginx/fastcgi_params;
+ include /etc/nginx/includes/fastcgi.conf;
+ #include /etc/nginx/includes/fastcgi_cache.conf;
+ fastcgi_pass unix:/run/php/php7.4-fpm.sock;
+ }
+
location ~ \.php73$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
@@ -238,7 +246,6 @@ server {
}
#include /etc/nginx/includes/error_pages.conf;
-
#include /etc/nginx/includes/fcgiwrap.conf;
}
diff --git a/etc/php/5.6/fpm/pool.d/lemper.conf b/etc/php/5.6/fpm/pool.d/lemper.conf
index d2b53e4d..3d50be59 100644
--- a/etc/php/5.6/fpm/pool.d/lemper.conf
+++ b/etc/php/5.6/fpm/pool.d/lemper.conf
@@ -18,7 +18,7 @@ pm.max_spare_servers = 3
pm.process_idle_timeout = 30s;
pm.max_requests = 500
-slowlog = /var/log/php/php5.6-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php5.6-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -34,7 +34,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php5.6-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php5.6-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php5.6-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/7.0/fpm/pool.d/lemper.conf b/etc/php/7.0/fpm/pool.d/lemper.conf
index ad1df500..923f3e2e 100644
--- a/etc/php/7.0/fpm/pool.d/lemper.conf
+++ b/etc/php/7.0/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php7.0-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php7.0-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php7.0-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php8.1-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php7.0-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/7.1/fpm/pool.d/lemper.conf b/etc/php/7.1/fpm/pool.d/lemper.conf
index 447370ec..08a919be 100644
--- a/etc/php/7.1/fpm/pool.d/lemper.conf
+++ b/etc/php/7.1/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php7.1-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php7.1-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php7.1-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php7.1-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php7.1-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/7.2/fpm/pool.d/lemper.conf b/etc/php/7.2/fpm/pool.d/lemper.conf
index fef28b51..c876cb85 100644
--- a/etc/php/7.2/fpm/pool.d/lemper.conf
+++ b/etc/php/7.2/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php7.2-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php7.2-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php7.2-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php7.2-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php7.2-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/7.3/fpm/pool.d/lemper.conf b/etc/php/7.3/fpm/pool.d/lemper.conf
index 297bc3b5..538ed8e9 100644
--- a/etc/php/7.3/fpm/pool.d/lemper.conf
+++ b/etc/php/7.3/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php7.3-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php7.3-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php7.3-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php7.3-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php7.3-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/7.4/fpm/pool.d/lemper.conf b/etc/php/7.4/fpm/pool.d/lemper.conf
index e32a0c08..f74abd61 100644
--- a/etc/php/7.4/fpm/pool.d/lemper.conf
+++ b/etc/php/7.4/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php7.4-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php7.4-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php7.4-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php7.4-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php7.4-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/8.0/fpm/pool.d/lemper.conf b/etc/php/8.0/fpm/pool.d/lemper.conf
index eaa6c2d8..7242b11d 100644
--- a/etc/php/8.0/fpm/pool.d/lemper.conf
+++ b/etc/php/8.0/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php8.0-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php8.0-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php8.0-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php8.0-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/etc/php/8.1/fpm/pool.d/lemper.conf b/etc/php/8.1/fpm/pool.d/lemper.conf
index f4c80aa9..131d01d1 100644
--- a/etc/php/8.1/fpm/pool.d/lemper.conf
+++ b/etc/php/8.1/fpm/pool.d/lemper.conf
@@ -21,7 +21,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php8.1-fpm_slow.$pool.log
+slowlog = /home/lemper/logs/php/php8.1-fpm_slow.log
request_slowlog_timeout = 10s
;chroot = /home/lemper
@@ -37,7 +37,8 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php8.1-fpm.$pool.log
+;php_admin_value[error_log] = /var/log/php/php8.1-fpm.$pool.log
+php_admin_value[error_log] = /home/lemper/logs/php/php8.1-fpm.log
php_admin_value[date.timezone] = UTC
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/lemper/.lemper/php/opcache
diff --git a/install.sh b/install.sh
index 1e38fb60..127fd2f9 100755
--- a/install.sh
+++ b/install.sh
@@ -36,7 +36,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/lib/lemper-adduser.sh b/lib/lemper-adduser.sh
index b0ba53c7..a923e844 100755
--- a/lib/lemper-adduser.sh
+++ b/lib/lemper-adduser.sh
@@ -1,4 +1,34 @@
-#!/bin/bash
+#!/usr/bin/env bash
+
+# +-------------------------------------------------------------------------+
+# | Lemper Create - Simple LEMP Virtual Host Creator |
+# +-------------------------------------------------------------------------+
+# | Copyright (c) 2014-2021 MasEDI.Net (https://masedi.net/lemper) |
+# +-------------------------------------------------------------------------+
+# | This source file is subject to the GNU General Public License |
+# | that is bundled with this package in the file LICENSE.md. |
+# | |
+# | If you did not receive a copy of the license and are unable to |
+# | obtain it through the world-wide-web, please send an email |
+# | to license@lemper.cloud so we can send you a copy immediately. |
+# +-------------------------------------------------------------------------+
+# | Authors: Edi Septriyanto |
+# +-------------------------------------------------------------------------+
+
+set -e
+
+# Version control.
+#PROG_NAME=$(basename "$0")
+#PROG_VER="2.x.x"
+#CMD_PARENT="lemper-cli"
+#CMD_NAME="adduser"
+
+# Make sure only root can access and not direct access.
+if ! declare -F "requires_root" &>/dev/null; then
+ echo "Direct access to this script is not permitted."
+ exit 1
+fi
+
function header_msg() {
clear
cat <<- EOL
@@ -12,12 +42,6 @@ function header_msg() {
EOL
}
-# Check if user is root
-if [[ "$(id -u)" -ne 0 ]]; then
- echo "Error: Please use root to add new user."
- exit 1
-fi
-
header_msg
echo -en "\nAdd new user? [y/n]: "
diff --git a/lib/lemper-create.sh b/lib/lemper-create.sh
index 031e97b0..ff3b3e15 100755
--- a/lib/lemper-create.sh
+++ b/lib/lemper-create.sh
@@ -23,79 +23,9 @@ PROG_VER="2.x.x"
CMD_PARENT="lemper-cli"
CMD_NAME="create"
-# Color decorator.
-RED=91
-GREEN=92
-YELLOW=93
-
-##
-# Helper Functions
-#
-function begin_color() {
- color="${1}"
- echo -e -n "\e[${color}m"
-}
-
-function end_color() {
- echo -e -n "\e[0m"
-}
-
-function echo_color() {
- color="${1}"
- shift
- begin_color "${color}"
- echo "$@"
- end_color
-}
-
-function error() {
- echo_color "${RED}" -n "Error: " >&2
- echo "$@" >&2
-}
-
-# Prints an error message and exits with an error code.
-function fail() {
- error "$@"
- echo >&2
- echo "For usage information, run this script with --help" >&2
- exit 1
-}
-
-function status() {
- echo_color "${GREEN}" "$@"
-}
-
-function warning() {
- echo_color "${YELLOW}" "$@"
-}
-
-function success() {
- echo_color "${GREEN}" -n "Success: " >&2
- echo "$@" >&2
-}
-
-function info() {
- echo_color "${YELLOW}" -n "Info: " >&2
- echo "$@" >&2
-}
-
-# Run command
-function run() {
- if "$DRYRUN"; then
- echo_color "${YELLOW}" -n "would run "
- echo "$@"
- else
- if ! "$@"; then
- local CMDSTR="$*"
- error "Failure running '${CMDSTR}', exiting."
- exit 1
- fi
- fi
-}
-
-# May need to run this as sudo!
-if [[ "$(id -u)" -ne 0 ]]; then
- error "This command can only be run by root."
+# Make sure only root can access and not direct access.
+if ! declare -F "requires_root" &>/dev/null; then
+ echo "Direct access to this script is not permitted."
exit 1
fi
@@ -109,7 +39,7 @@ done
if [[ ${#NO_PACKAGES[@]} -gt 0 ]]; then
printf -v NO_PACKAGES_STR '%s, ' "${NO_PACKAGES[@]}"
- error "${PROG_NAME} requires: ${NO_PACKAGES_STR%, }, please install it first!"
+ error "${PROG_NAME} ${COMMAND_NAME} requires: ${NO_PACKAGES_STR%, }, please install it first!"
echo "help: run 'sudo apt-get install ${NO_PACKAGES[*]}'"
exit 1
fi
@@ -767,7 +697,7 @@ pm.max_requests = 500
pm.status_path = /status
ping.path = /ping
-slowlog = /var/log/php/php${PHP_VERSION}-fpm_slow.\$pool.log
+slowlog = /home/${USERNAME}/logs/php/php${PHP_VERSION}-fpm_slow.log
request_slowlog_timeout = 5s
chdir = /home/${USERNAME}
@@ -782,7 +712,7 @@ php_flag[display_errors] = On
;php_admin_value[error_reporting] = E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_WARNING & ~E_NOTICE
;php_admin_value[disable_functions] = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,passthru,popen,proc_open,shell_exec,system
php_admin_flag[log_errors] = On
-php_admin_value[error_log] = /var/log/php/php${PHP_VERSION}-fpm.\$pool.log
+php_admin_value[error_log] = /home/${USERNAME}/logs/php/php${PHP_VERSION}-fpm.log
php_admin_value[date.timezone] = ${TIMEZONE}
php_admin_value[memory_limit] = 128M
php_admin_value[opcache.file_cache] = /home/${USERNAME}/.lemper/php/opcache
@@ -955,7 +885,7 @@ function init_lemper_create() {
ENABLE_FAIL2BAN=false
TMPDIR="/tmp/lemper"
- # Test mode
+ # Dry run (test mode).
DRYRUN=false
# Args counter
@@ -1397,7 +1327,7 @@ function init_lemper_create() {
--admin_user="${APP_ADMIN_USER}" --admin_password="${APP_ADMIN_PASS}" \
--admin_email="${APP_ADMIN_EMAIL}" --path="${WEBROOT}" && \
run sudo -u "${USERNAME}" -i -- wp-cli plugin install \
- akismet classic-editor nginx-helper redis-cache statically --activate --path="${WEBROOT}"
+ akismet autoptimize cache-enabler classic-editor nginx-helper redis-cache --activate --path="${WEBROOT}"
fi
# Install WooCommerce.
@@ -1442,7 +1372,7 @@ function init_lemper_create() {
--title="WordPress Multi-site Managed by LEMPer" --admin_user="${APP_ADMIN_USER}" \
--admin_password="${APP_ADMIN_PASS}" --admin_email="${APP_ADMIN_EMAIL}" --path="${WEBROOT}" && \
run sudo -u "${USERNAME}" -i -- wp-cli plugin install \
- akismet classic-editor nginx-helper redis-cache statically --activate-network --path="${WEBROOT}"
+ akismet autoptimize cache-enabler classic-editor nginx-helper redis-cache --activate-network --path="${WEBROOT}"
fi
# Mercator domain mapping.
diff --git a/lib/lemper-db.sh b/lib/lemper-db.sh
index f2534a50..838a213f 100755
--- a/lib/lemper-db.sh
+++ b/lib/lemper-db.sh
@@ -23,94 +23,20 @@ PROG_VER="2.x.x"
CMD_PARENT="lemper-cli"
CMD_NAME="db"
-# Test mode.
-DRYRUN=false
-
-# Color decorator.
-RED=91
-GREEN=92
-YELLOW=93
-
-##
-# Helper Functions
-#
-function begin_color() {
- color="${1}"
- echo -e -n "\e[${color}m"
-}
-
-function end_color() {
- echo -e -n "\e[0m"
-}
-
-function echo_color() {
- color="${1}"
- shift
- begin_color "${color}"
- echo "$@"
- end_color
-}
-
-function error() {
- echo_color "${RED}" -n "Error: " >&2
- echo "$@" >&2
-}
-
-# Prints an error message and exits with an error code.
-function fail() {
- error "$@"
- #echo >&2
- echo "For usage information, run this script with --help" >&2
- exit 1
-}
-
-function status() {
- echo_color "${GREEN}" "$@"
-}
-
-function warning() {
- echo_color "${YELLOW}" "$@"
-}
-
-function success() {
- echo_color "${GREEN}" -n "Success: " >&2
- echo "$@" >&2
-}
-
-function info() {
- echo_color "${YELLOW}" -n "Info: " >&2
- echo "$@" >&2
-}
-
-# Run command
-function run() {
- if "${DRYRUN}"; then
- echo_color "${YELLOW}" -n "would run "
- echo "$@"
- else
- if ! "$@"; then
- local CMDSTR="$*"
- error "Failure running '${CMDSTR}', exiting."
- exit 1
- fi
- fi
-}
-
-# May need to run this as sudo!
-if [[ "$(id -u)" -ne 0 ]]; then
- error "This command can only be run by root."
+# Make sure only root can access and not direct access.
+if [[ "$(type -t requires_root)" != "function" ]]; then
+ echo "Direct access to this script is not permitted."
exit 1
fi
-
##
# Main Functions
-#
+##
##
# Trim whitespace.
# Ref: https://stackoverflow.com/a/3352015/12077262
-#
+##
function str_trim() {
local str="$*"
@@ -126,7 +52,7 @@ function str_trim() {
##
# Convert string to uppercase.
# Ref: https://unix.stackexchange.com/a/51987
-#
+##
function str_to_upper() {
local str="$*"
@@ -135,7 +61,7 @@ function str_to_upper() {
##
# Prints help.
-#
+##
function cmd_help() {
cat <<- EOL
${CMD_PARENT} ${CMD_NAME} ${PROG_VER}
@@ -302,7 +228,7 @@ function cmd_users() {
##
# Initialize account subcommand.
-#
+##
function sub_cmd_account() {
# account subcommands
function cmd_account_help() {
@@ -541,8 +467,8 @@ EOL
}
##
-# Main database operations.
-#
+# Main Database Operations.
+##
function db_ops() {
OPTS=$(getopt -o a:H:P:u:p:n:b:C:g:f:q:x:DrhVv \
-l action:,dbhost:,dbport:,dbuser:,dbpass:,dbname:,dbprefix:,dbcollation:,dbprivileges:,dbfile:,dbquery:,extra-args: \
@@ -559,79 +485,97 @@ function db_ops() {
while true
do
case "${1}" in
- -a | --action) shift
+ -a | --action)
+ shift
local ACTION="${1}"
MAIN_ARGS=$((MAIN_ARGS + 1))
shift
;;
- -b | --dbprefix) shift
+ -b | --dbprefix)
+ shift
DBPREFIX="${1}"
shift
;;
- -C | --dbcollation) shift
+ -C | --dbcollation)
+ shift
DBCOLLATION="${1}"
shift
;;
- -f | --dbfile) shift
+ -f | --dbfile)
+ shift
DBFILE="${1}"
shift
;;
- -g | --dbprivileges) shift
+ -g | --dbprivileges)
+ shift
DBPRIVILEGES="${1}"
shift
;;
- -H | --dbhost) shift
+ -H | --dbhost)
+ shift
DBHOST=${1}
shift
;;
- -n | --dbname) shift
+ -n | --dbname)
+ shift
DBNAME="${1}"
shift
;;
- -p | --dbpass) shift
+ -p | --dbpass)
+ shift
DBPASS="${1}"
shift
;;
- -P | --dbport) shift
+ -P | --dbport)
+ shift
DBPORT=${1}
shift
;;
- -q | --dbquery) shift
+ -q | --dbquery)
+ shift
DBQUERY="${1}"
shift
;;
- -u | --dbuser) shift
+ -u | --dbuser)
+ shift
DBUSER="${1}"
shift
;;
- -x | --extra-args) shift
+ -x | --extra-args)
+ shift
EXTRA_ARGS="${1}"
shift
;;
- -D | --dry-run) shift
+ -D | --dry-run)
+ shift
DRYRUN=true
;;
- -r | --root) shift
+ -r | --root)
+ shift
USEROOT=true
;;
- -V | --verbose) shift
+ -V | --verbose)
+ shift
VERBOSE=true
;;
- -h | --help) shift
+ -h | --help)
+ shift
# Bypass args.
BYPASSED_ARGS="${BYPASSED_ARGS} --help"
;;
- -v | --version) shift
+ -v | --version)
+ shift
# Bypass args.
BYPASSED_ARGS="${BYPASSED_ARGS} --version"
;;
- --) shift
+ --)
+ shift
break
;;
*)
- fail "Invalid argument: ${1}"
+ fail "unrecognized option '${1}'"
exit 1
;;
esac
@@ -860,8 +804,8 @@ function db_ops() {
}
##
-# Main DB CLI Wrapper
-#
+# Main Database CLI Wrapper
+##
function init_lemper_db() {
# Check command line arguments.
if [[ -n "${1}" ]]; then
diff --git a/lib/lemper-manage.sh b/lib/lemper-manage.sh
index e025696c..697088bc 100755
--- a/lib/lemper-manage.sh
+++ b/lib/lemper-manage.sh
@@ -23,93 +23,20 @@ PROG_VER="2.x.x"
CMD_PARENT="lemper-cli"
CMD_NAME="manage"
-# Test mode.
-DRYRUN="false"
-
-# Color decorator.
-RED=91
-GREEN=92
-YELLOW=93
-
-##
-# Helper Functions
-#
-function begin_color() {
- color="${1}"
- echo -e -n "\e[${color}m"
-}
-
-function end_color() {
- echo -e -n "\e[0m"
-}
-
-function echo_color() {
- color="${1}"
- shift
- begin_color "${color}"
- echo "$@"
- end_color
-}
-
-function error() {
- echo_color "${RED}" -n "Error: " >&2
- echo "$@" >&2
-}
-
-# Prints an error message and exits with an error code.
-function fail() {
- error "$@"
- echo "For usage information, run this script with --help" >&2
- exit 1
-}
-
-function status() {
- echo_color "${GREEN}" "$@"
-}
-
-function warning() {
- echo_color "${YELLOW}" "$@"
-}
-
-function success() {
- echo_color "${GREEN}" -n "Success: " >&2
- echo "$@" >&2
-}
-
-function info() {
- echo_color "${YELLOW}" -n "Info: " >&2
- echo "$@" >&2
-}
-
-# Run command
-function run() {
- if "${DRYRUN}"; then
- echo_color "${YELLOW}" -n "would run "
- echo "$@"
- else
- if ! "$@"; then
- local CMDSTR="$*"
- error "Failure running '${CMDSTR}', exiting."
- exit 1
- fi
- fi
-}
-
-# May need to run this as sudo!
-if [[ "$(id -u)" -ne 0 ]]; then
- error "This command can only be run by root."
+# Make sure only root can access and not direct access.
+if ! declare -F "requires_root" &>/dev/null; then
+ echo "Direct access to this script is not permitted."
exit 1
fi
-
##
# Main Functions
-#
+##
##
# Show usage
# output to STDERR.
-#
+##
function show_usage() {
cat <<- EOL
${CMD_PARENT} ${CMD_NAME} ${PROG_VER}
@@ -171,7 +98,7 @@ EOL
##
# Enable vhost.
-#
+##
function enable_vhost() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -192,7 +119,7 @@ function enable_vhost() {
##
# Disable vhost.
-#
+##
function disable_vhost() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -213,7 +140,7 @@ function disable_vhost() {
##
# Remove vhost.
-#
+##
function remove_vhost() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -320,7 +247,7 @@ function remove_vhost() {
##
# Enable fail2ban for virtual host.
-#
+##
function enable_fail2ban() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -358,8 +285,8 @@ EOL
}
##
-# Enable fail2ban for virtual host.
-#
+# Disable fail2ban for virtual host.
+##
function disable_fail2ban() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -378,7 +305,7 @@ function disable_fail2ban() {
##
# Enable Nginx's fastcgi cache.
-#
+##
function enable_fastcgi_cache() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -394,18 +321,18 @@ function enable_fastcgi_cache() {
# enable fastcgi_cache conf
run sed -i "s|#include\ /etc/nginx/includes/fastcgi_cache.conf|include\ /etc/nginx/includes/fastcgi_cache.conf|g" \
"/etc/nginx/sites-available/${DOMAIN}.conf"
+
+ # Reload Nginx.
+ reload_nginx
else
info "FastCGI cache is not enabled. There is no cached configuration."
exit 1
fi
-
- # Reload Nginx.
- reload_nginx
}
##
# Disable Nginx's fastcgi cache.
-#
+##
function disable_fastcgi_cache() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -421,18 +348,18 @@ function disable_fastcgi_cache() {
# enable fastcgi_cache conf
run sed -i "s|^\ include\ /etc/nginx/includes/fastcgi_cache.conf|\ #include\ /etc/nginx/includes/fastcgi_cache.conf|g" \
"/etc/nginx/sites-available/${DOMAIN}.conf"
+
+ # Reload Nginx.
+ reload_nginx
else
info "FastCGI cache is not enabled. There is no cached configuration."
exit 1
fi
-
- # Reload Nginx.
- reload_nginx
}
##
# Enable Nginx's Mod PageSpeed.
-#
+##
function enable_mod_pagespeed() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -441,7 +368,7 @@ function enable_mod_pagespeed() {
echo "Enabling Mod PageSpeed for ${DOMAIN}..."
if [[ -f /etc/nginx/includes/mod_pagespeed.conf && -f /etc/nginx/modules-enabled/50-mod-pagespeed.conf ]]; then
- # enable mod pagespeed
+ # Enable mod pagespeed.
run sed -i "s|#include\ /etc/nginx/mod_pagespeed|include\ /etc/nginx/mod_pagespeed|g" /etc/nginx/nginx.conf
run sed -i "s|#include\ /etc/nginx/includes/mod_pagespeed.conf|include\ /etc/nginx/includes/mod_pagespeed.conf|g" \
"/etc/nginx/sites-available/${DOMAIN}.conf"
@@ -450,25 +377,25 @@ function enable_mod_pagespeed() {
run sed -i "s|#pagespeed\ Disallow|pagespeed\ Disallow|g" "/etc/nginx/sites-available/${DOMAIN}.conf"
run sed -i "s|#pagespeed\ Domain|pagespeed\ Domain|g" "/etc/nginx/sites-available/${DOMAIN}.conf"
- # If SSL enabled, ensure to also to enable PageSpeed related vars.
+ # If SSL enabled, ensure to also enable PageSpeed related vars.
#if grep -qwE "^\ include\ /etc/nginx/includes/ssl.conf" "/etc/nginx/sites-available/${DOMAIN}.conf"; then
# run sed -i "s/#pagespeed\ FetchHttps/pagespeed\ FetchHttps/g" \
# "/etc/nginx/sites-available/${DOMAIN}.conf"
# run sed -i "s/#pagespeed\ MapOriginDomain/pagespeed\ MapOriginDomain/g" \
# "/etc/nginx/sites-available/${DOMAIN}.conf"
#fi
+
+ # Reload Nginx.
+ reload_nginx
else
info "Mod PageSpeed is not enabled. NGiNX must be installed with PageSpeed module."
exit 1
fi
-
- # Reload Nginx.
- reload_nginx
}
##
# Disable Nginx's Mod PageSpeed.
-#
+##
function disable_mod_pagespeed() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -492,18 +419,18 @@ function disable_mod_pagespeed() {
# run sed -i "s/^\ pagespeed\ MapOriginDomain/\ #pagespeed\ MapOriginDomain/g" \
# "/etc/nginx/sites-available/${DOMAIN}.conf"
#fi
+
+ # Reload Nginx.
+ reload_nginx
else
info "Mod PageSpeed is not enabled. NGiNX must be installed with PageSpeed module."
exit 1
fi
-
- # Reload Nginx.
- reload_nginx
}
##
# Enable HTTPS (HTTP over SSL).
-#
+##
function enable_ssl() {
# Verify user input hostname (domain name).
local DOMAIN=${1}
@@ -591,18 +518,15 @@ EOL
reload_nginx
else
warning -e "\nOops, Nginx HTTPS server block already exists. Please inspect manually for further action!"
- exit 1
fi
else
info "Updating HTTPS config in dry run mode."
fi
-
- exit 0
}
##
# Disable HTTPS (HTTP over SSL).
-#
+##
function disable_ssl() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -630,13 +554,11 @@ function disable_ssl() {
else
info "Disabling HTTPS config in dry run mode."
fi
-
- exit 0
}
##
# Disable HTTPS and remove Let's Encrypt SSL certificate.
-#
+##
function remove_ssl() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -660,6 +582,8 @@ function remove_ssl() {
else
fail "Certbot executable binary not found. Install it first!"
fi
+
+ reload_nginx
else
info "SSL certificate removed in dry run mode."
fi
@@ -667,7 +591,7 @@ function remove_ssl() {
##
# Renew Let's Encrypt SSL certificate.
-#
+##
function renew_ssl() {
# Verify user input hostname (domain name)
local DOMAIN=${1}
@@ -701,16 +625,16 @@ function renew_ssl() {
else
info "Certificate file not found. May be your SSL is not activated yet."
fi
+
+ reload_nginx
else
info "Renew SSL certificate in dry run mode."
fi
-
- exit 0
}
##
# Enable Brotli compression module.
-#
+##
function enable_brotli() {
local DOMAIN=${1}
verify_vhost "${DOMAIN}"
@@ -748,7 +672,7 @@ function enable_brotli() {
##
# Enable Gzip compression module,
# enabled by default.
-#
+##
function enable_gzip() {
local DOMAIN=${1}
verify_vhost "${DOMAIN}"
@@ -785,7 +709,7 @@ function enable_gzip() {
##
# Disable Gzip/Brotli compression module
-#
+##
function disable_compression() {
local DOMAIN=${1}
verify_vhost "${DOMAIN}"
@@ -805,7 +729,7 @@ function disable_compression() {
##
# Verify if virtual host exists.
-#
+##
function verify_vhost() {
if [[ -z "${1}" ]]; then
error "Virtual host (vhost) or domain name is required."
@@ -826,13 +750,13 @@ function verify_vhost() {
##
# Reload NGiNX safely.
-#
+##
function reload_nginx() {
# Reload Nginx
echo "Reloading NGiNX configuration..."
if [[ -e /var/run/nginx.pid ]]; then
- if nginx -t 2>/dev/null > /dev/null; then
+ if nginx -t > /dev/null 2>&1; then
service nginx reload -s > /dev/null 2>&1
else
error "Configuration couldn't be validated. Please correct the error below:";
@@ -866,7 +790,7 @@ function reload_nginx() {
##
# Main Manage CLI Wrapper
-#
+##
function init_lemper_manage() {
OPTS=$(getopt -o c:d:e:f:p:r:s:bghv \
-l enable:,disable:,remove:,enable-fail2ban:,disable-fail2ban:,enable-fastcgi-cache:,disable-fastcgi-cache: \
@@ -917,18 +841,22 @@ function init_lemper_manage() {
;;
-s | --enable-ssl)
enable_ssl "${2}"
+ exit
shift 2
;;
--disable-ssl)
disable_ssl "${2}"
+ exit
shift 2
;;
--remove-ssl)
remove_ssl "${2}"
+ exit
shift 2
;;
--renew-ssl)
renew_ssl "${2}"
+ exit
shift 2
;;
-b | --enable-brotli)
diff --git a/lib/lemper-site.sh b/lib/lemper-site.sh
new file mode 100755
index 00000000..4c3363db
--- /dev/null
+++ b/lib/lemper-site.sh
@@ -0,0 +1,93 @@
+#!/usr/bin/env bash
+
+# +-------------------------------------------------------------------------+
+# | Lemper Site - Simple LEMPer Stack Site (vhost) Manager |
+# +-------------------------------------------------------------------------+
+# | Copyright (c) 2014-2021 MasEDI.Net (https://masedi.net/lemper) |
+# +-------------------------------------------------------------------------+
+# | This source file is subject to the GNU General Public License |
+# | that is bundled with this package in the file LICENSE.md. |
+# | |
+# | If you did not receive a copy of the license and are unable to |
+# | obtain it through the world-wide-web, please send an email |
+# | to license@lemper.cloud so we can send you a copy immediately. |
+# +-------------------------------------------------------------------------+
+# | Authors: Edi Septriyanto |
+# +-------------------------------------------------------------------------+
+
+set -e
+
+# Make sure only root can access and not direct access.
+if [[ "$(type -t requires_root)" != "function" ]]; then
+ echo "Direct access to this script is not permitted."
+ exit 1
+fi
+
+# Version control.
+#PROG_NAME=$(basename "$0")
+#PROG_VER="2.x.x"
+CMD_PARENT="lemper-cli"
+CMD_NAME="site"
+
+if [ -z "${CLI_PLUGINS_DIR}" ]; then
+ CLI_PLUGINS_DIR="/etc/lemper/cli-plugins"
+fi
+
+function site_subcmd_help() {
+ cmd_help
+ exit 0
+}
+
+function site_subcmd_version() {
+ cmd_version
+ exit 0
+}
+
+##
+# LEMPer CLI 'site' subcommand wrapper.
+#
+# Usage:
+# lemper-cli site [options] [...]
+##
+function init_lemper_site() {
+ # Check command line arguments.
+ if [[ -n "${1}" ]]; then
+ CMD="${1}"
+ shift # Pass the remaining arguments to the next subcommand.
+
+ case ${CMD} in
+ help | -h | --help)
+ site_subcmd_help
+ exit 0
+ ;;
+ version | -v | --version)
+ site_subcmd_version
+ exit 0
+ ;;
+ *)
+ if declare -f "site_subcmd_${CMD}" &>/dev/null 2>&1; then
+ # Run subcommand function if exists.
+ "site_subcmd_${CMD}" "$@"
+ exit 0
+ elif [[ -x "${CLI_PLUGINS_DIR}/lemper-site-${CMD}" ]]; then
+ # Source the plugin executable file.
+ # shellcheck disable=SC1090
+ . "${CLI_PLUGINS_DIR}/lemper-site-${CMD}" "$@"
+ exit 0
+ else
+ echo "${CMD_PARENT} ${CMD_NAME}: '${CMD}' is not ${CMD_NAME} subcommand."
+ echo "See '${CMD_PARENT} ${CMD_NAME} --help' for more information."
+ exit 1
+ fi
+ ;;
+ esac
+ else
+ echo "${CMD_PARENT} ${CMD_NAME}: missing required arguments."
+ echo "See '${CMD_PARENT} ${CMD_NAME} --help' for more information."
+ exit 1
+ fi
+}
+
+# Start running things from a call at the end so if this script is executed
+# after a partial download it doesn't do anything.
+init_lemper_site "$@"
diff --git a/remove.sh b/remove.sh
index f0e362e8..a93a6464 100755
--- a/remove.sh
+++ b/remove.sh
@@ -36,7 +36,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/cleanup_server.sh b/scripts/cleanup_server.sh
index 806a8c5d..32f5fdcc 100755
--- a/scripts/cleanup_server.sh
+++ b/scripts/cleanup_server.sh
@@ -21,7 +21,7 @@ else
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/helper.sh b/scripts/helper.sh
index 0443304d..b1b1041b 100644
--- a/scripts/helper.sh
+++ b/scripts/helper.sh
@@ -65,6 +65,16 @@ function fail() {
exit 1
}
+function success() {
+ echo_color "${GREEN}" -n "Success: " >&2
+ echo "$@" >&2
+}
+
+function info() {
+ echo_color "${YELLOW}" -n "Info: " >&2
+ echo "$@" >&2
+}
+
function status() {
echo_color "${GREEN}" "$@"
}
@@ -73,14 +83,32 @@ function warning() {
echo_color "${YELLOW}" "$@"
}
-function success() {
- echo_color "${GREEN}" -n "Success: " >&2
- echo "$@" >&2
+function echo_ok() {
+ echo_color "${GREEN}" "$@"
}
-function info() {
- echo_color "${YELLOW}" -n "Info: " >&2
- echo "$@" >&2
+function echo_warn() {
+ echo_color "${YELLOW}" "$@"
+}
+
+function echo_err() {
+ echo_color "${RED}" "$@"
+}
+
+# Make sure only root can run LEMPer script.
+function requires_root() {
+ if [[ "$(id -u)" -ne 0 ]]; then
+ if ! hash sudo 2>/dev/null; then
+ echo "Installer script must be run as 'root' or with sudo."
+ exit 1
+ else
+ #echo "Switching to root user to run installer script."
+ sudo -E "$0" "$@"
+ exit 0
+ fi
+ fi
+
+ #success "Root privileges granted."
}
# Run command
@@ -298,14 +326,6 @@ function validate_fqdn() {
fi
}
-# Make sure only root can run LEMPer script.
-function requires_root() {
- if [[ "$(id -u)" -ne 0 ]]; then
- error "This command can only be run by root."
- exit 1
- fi
-}
-
# Get general distribution name.
function get_distrib_name() {
if [[ -f "/etc/os-release" ]]; then
diff --git a/scripts/install_certbotle.sh b/scripts/install_certbotle.sh
index ea4b4f1a..13142317 100755
--- a/scripts/install_certbotle.sh
+++ b/scripts/install_certbotle.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
@@ -22,14 +22,18 @@ preflight_system_check
# Install Certbot Let's Encrypt.
function init_certbotle_install() {
if [[ "${AUTO_INSTALL}" == true ]]; then
- DO_INSTALL_CERTBOT="y"
+ if [[ "${INSTALL_CERTBOT}" == true ]]; then
+ DO_INSTALL_CERTBOT="y"
+ else
+ DO_INSTALL_CERTBOT="n"
+ fi
else
while [[ "${DO_INSTALL_CERTBOT}" != "y" && "${DO_INSTALL_CERTBOT}" != "n" ]]; do
read -rp "Do you want to install Certbot Let's Encrypt client? [y/n]: " -i y -e DO_INSTALL_CERTBOT
done
fi
- if [[ ${DO_INSTALL_CERTBOT} == y* && ${INSTALL_CERTBOT} == true ]]; then
+ if [[ ${DO_INSTALL_CERTBOT} == y* || ${DO_INSTALL_CERTBOT} == Y* ]]; then
echo "Installing Certbot Let's Encrypt client..."
DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)}
diff --git a/scripts/install_dependencies.sh b/scripts/install_dependencies.sh
index fd40d0c0..b9138077 100755
--- a/scripts/install_dependencies.sh
+++ b/scripts/install_dependencies.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_fail2ban.sh b/scripts/install_fail2ban.sh
index 0a08034d..863b7835 100755
--- a/scripts/install_fail2ban.sh
+++ b/scripts/install_fail2ban.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_imagemagick.sh b/scripts/install_imagemagick.sh
index fbb07e00..e12dc848 100755
--- a/scripts/install_imagemagick.sh
+++ b/scripts/install_imagemagick.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_mailer.sh b/scripts/install_mailer.sh
index dd5e039d..ebeee804 100755
--- a/scripts/install_mailer.sh
+++ b/scripts/install_mailer.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_mariadb.sh b/scripts/install_mariadb.sh
index 477c2be5..d1af2193 100755
--- a/scripts/install_mariadb.sh
+++ b/scripts/install_mariadb.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_memcached.sh b/scripts/install_memcached.sh
index 728205a0..efa6cf8a 100755
--- a/scripts/install_memcached.sh
+++ b/scripts/install_memcached.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_mongodb.sh b/scripts/install_mongodb.sh
index dea1dc24..ef8d27c6 100755
--- a/scripts/install_mongodb.sh
+++ b/scripts/install_mongodb.sh
@@ -3,7 +3,7 @@
# MongoDB installer
# Ref : https://www.linode.com/docs/databases/mongodb/install-mongodb-on-ubuntu-16-04
# Min. Requirement : GNU/Linux Ubuntu 18.04
-# Last Build : 11/12/2021
+# Last Build : 24/12/2021
# Author : MasEDI.Net (me@masedi.net)
# Since Version : 1.0.0
@@ -15,23 +15,20 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
+DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)}
+RELEASE_NAME=${RELEASE_NAME:-$(get_release_name)}
+MONGODB_VERSION=${MONGODB_VERSION:-"5.0"}
+[[ "${RELEASE_NAME}" == "jessie" || "${RELEASE_NAME}" == "xenial" ]] && MONGODB_VERSION="4.4"
+
##
# Add MongoDB repository.
-#
+##
function add_mongodb_repo() {
- echo "Adding MongoDB ${MONGODB_VERSION} repository..."
-
- DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)}
- RELEASE_NAME=${RELEASE_NAME:-$(get_release_name)}
- MONGODB_VERSION=${MONGODB_VERSION:-"5.0"}
-
- [[ "${RELEASE_NAME}" == "jessie" || "${RELEASE_NAME}" == "xenial" ]] && MONGODB_VERSION="4.4"
-
local DISTRIB_ARCH
case ${ARCH} in
i386 | i486| i586 | i686)
@@ -53,20 +50,30 @@ function add_mongodb_repo() {
case ${DISTRIB_NAME} in
debian)
- if [ ! -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]; then
+ if [[ ! -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]]; then
+ echo "Adding MongoDB repository key..."
+
+ run bash -c "wget -qO - 'https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc' | apt-key add -"
+
+ echo "Adding MongoDB repository..."
+
run touch "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list"
run bash -c "echo 'deb [ arch=${DISTRIB_ARCH} ] https://repo.mongodb.org/apt/debian ${RELEASE_NAME}/mongodb-org/${MONGODB_VERSION} main' > /etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list"
- run bash -c "wget -qO - 'https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc' | apt-key add -"
run apt-get update -qq -y
else
info "MongoDB ${MONGODB_VERSION} repository already exists."
fi
;;
ubuntu)
- if [ ! -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]; then
+ if [[ ! -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]]; then
+ echo "Adding MongoDB repository key..."
+
+ run bash -c "wget -qO - 'https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc' | apt-key add -"
+
+ echo "Adding MongoDB repository..."
+
run touch "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list"
run bash -c "echo 'deb [ arch=${DISTRIB_ARCH} ] https://repo.mongodb.org/apt/ubuntu ${RELEASE_NAME}/mongodb-org/${MONGODB_VERSION} multiverse' > /etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list"
- run bash -c "wget -qO - 'https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc' | apt-key add -"
run apt-get update -qq -y
else
info "MongoDB ${MONGODB_VERSION} repository already exists."
@@ -103,21 +110,46 @@ function init_mongodb_install() {
# Add repository.
add_mongodb_repo
- echo "Installing MongoDB server.."
+ echo "Installing MongoDB server..."
- run apt-get install -qq -y libbson-1.0 libmongoc-1.0-0 \
- mongodb-org mongodb-org-server mongodb-org-shell mongodb-org-tools
+ run apt-get install -qq -y libbson-1.0 libmongoc-1.0-0 mongodb-org mongodb-org-server \
+ mongodb-org-shell mongodb-org-tools mongodb-org-mongos mongodb-database-tools \
+ mongodb-org-database-tools-extra mongodb-mongosh
- # Enable in start-up
- run systemctl start mongod.service
- run systemctl enable mongod
+ if [[ "${DRYRUN}" != true ]]; then
+ # Enable in start-up.
+ echo "Enable MongoDB systemd service..."
- if [[ "${DRYRUN}" == true ]]; then
- info "MongoDB server installed in dry run mode."
- else
- echo "MongoDB installation completed."
- echo "After installation finished, you can add a MongoDB administrative user. Example command lines below:";
- cat <<- EOL
+ run systemctl start mongod.service
+ run systemctl enable mongod
+
+ if [[ $(systemctl is-active mongod) == 'active' ]]; then
+ echo "MongoDB server is running."
+ else
+ echo "MongoDB server is not running."
+ fi
+
+ # Add MongoDB default admin user.
+ if [[ -n $(command -v mongosh) && $(pgrep -c mongod) -gt 0 ]]; then
+ echo "Final test MongoDB service..."
+
+ sleep 3 # Wait for MongoDB to completely start.
+
+ MONGODB_ADMIN_USER=${MONGODB_ADMIN_USER:-"lemperdb"}
+ MONGODB_ADMIN_PASSWORD=${MONGODB_ADMIN_PASSWORD:-"$(openssl rand -base64 64 | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"}
+
+ run mongosh admin \
+ --eval "\"db.createUser({'user': '${MONGODB_ADMIN_USER}', 'pwd': '${MONGODB_ADMIN_PASSWORD}', 'roles':[{'role': 'root', 'db': 'admin'}]});\""
+
+ # Save config.
+ save_config -e "MONGODB_HOST=127.0.0.1\nMONGODB_PORT=27017\nMONGODB_ADMIN_USER=${MONGODB_ADMIN_USER}\nMONGODB_ADMIN_PASS=${MONGODB_ADMIN_PASSWORD}"
+
+ # Save log.
+ save_log -e "MongoDB default admin user is enabled, here is your admin credentials:\nAdmin username: ${MONGODB_ADMIN_USER} | Admin password: ${MONGODB_ADMIN_PASSWORD}\nSave this credentials and use it to authenticate your MongoDB connection."
+ else
+ echo "MongoDB installation completed with errors on start-up, please check the log file."
+ echo -e "After installation finished, you can add a MongoDB administrative user.\nExample command lines below:";
+ cat <<- EOL
mongosh
> use admin
@@ -134,29 +166,16 @@ mongosh -u admin -p --authenticationDatabase user-data
> db.exampleCollection.find({"name" : "John Doe"})
EOL
-
- # Add MongoDB default admin user.
- if [[ -n $(command -v mongosh) ]]; then
- echo "Adding MongoDB default admin user.."
-
- MONGODB_ADMIN_USER=${MONGODB_ADMIN_USER:-"lemperdb"}
- MONGODB_ADMIN_PASSWORD=${MONGODB_ADMIN_PASSWORD:-"$(openssl rand -base64 64 | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1)"}
-
- run mongosh admin --eval "\"db.createUser({'user': '${MONGODB_ADMIN_USER}', 'pwd': '${MONGODB_ADMIN_PASSWORD}', 'roles':[{'role': 'root', 'db': 'admin'}]});\""
-
- # Save config.
- save_config -e "MONGODB_HOST=127.0.0.1\nMONGODB_PORT=27017\nMONGODB_ADMIN_USER=${MONGODB_ADMIN_USER}\nMONGODB_ADMIN_PASS=${MONGODB_ADMIN_PASSWORD}"
-
- # Save log.
- save_log -e "MongoDB default admin user is enabled, here is your admin credentials:\nAdmin username: ${MONGODB_ADMIN_USER} | Admin password: ${MONGODB_ADMIN_PASSWORD}\nSave this credentials and use it to authenticate your MongoDB connection."
fi
+ else
+ info "MongoDB server installed in dry run mode."
fi
else
info "MongoDB server installation skipped."
fi
}
-echo "[MongoDB Server Installation]"
+echo "[MongoDB ${MONGODB_VERSION} Server Installation]"
# Start running things from a call at the end so if this script is executed
# after a partial download it doesn't do anything.
diff --git a/scripts/install_nginx.sh b/scripts/install_nginx.sh
index 798d16ab..99176625 100755
--- a/scripts/install_nginx.sh
+++ b/scripts/install_nginx.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_phalcon.sh b/scripts/install_phalcon.sh
index 19de1919..c16f51bc 100755
--- a/scripts/install_phalcon.sh
+++ b/scripts/install_phalcon.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
diff --git a/scripts/install_php.sh b/scripts/install_php.sh
index 5450d9b0..9941d33d 100755
--- a/scripts/install_php.sh
+++ b/scripts/install_php.sh
@@ -2,7 +2,7 @@
# PHP Installer
# Min. Requirement : GNU/Linux Ubuntu 18.04
-# Last Build : 11/12/2021
+# Last Build : 09/01/2022
# Author : MasEDI.Net (me@masedi.net)
# Since Version : 1.0.0
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
@@ -195,6 +195,14 @@ function install_php() {
run mkdir -p /var/log/php
fi
+ if [[ ! -d "/home/${LEMPER_USERNAME}/logs/php" ]]; then
+ run mkdir -p "/home/${LEMPER_USERNAME}/logs/php"
+ fi
+
+ # Log rotation.
+ run cp -f "etc/logrotate.d/php${PHPv}-fpm" /etc/logrotate.d/ && \
+ run chmod 0644 "/etc/logrotate.d/php${PHPv}-fpm"
+
# Optimize PHP & FPM configuration.
optimize_php_fpm "${PHPv}"
fi
@@ -253,6 +261,12 @@ function optimize_php_fpm() {
run cp -f "etc/php/${PHPv}/fpm/php.ini" "/etc/php/${PHPv}/fpm/"
else
if [[ "${DRYRUN}" != true ]]; then
+ if [[ "${ENVIRONMENT}" =~ "prod" ]]; then
+ OVT="${OVT:-"0"}"
+ else
+ OVT="${OVT:-"1"}"
+ fi
+
cat >> "/etc/php/${PHPv}/fpm/php.ini" <> /etc/sysctl.conf <\ 'redispasswordhere'|'auth'\ =>\ '${REDIS_PASSWORD}'|g" includes/config.inc.php
- fi
- else
- run cd redisadmin && \
- run "${COMPOSER_BIN}" -q update
+ if [[ "${REDIS_REQUIRE_PASSWORD}" == true ]]; then
+ run sed -i "s|//'auth'\ =>\ 'redispasswordhere'|'auth'\ =>\ '${REDIS_PASSWORD}'|g" includes/config.inc.php
fi
-
- run cd "${CURRENT_DIR}" || return 1
+ else
+ run cd redisadmin && \
+ run "${COMPOSER_BIN}" -q update
fi
+ run cd "${CURRENT_DIR}" || return 1
+ [ -f /usr/share/nginx/html/lcp/redisadmin/index.php ] && echo_ok "OK"
+
+
# Assign ownership properly.
run chown -hR www-data:www-data /usr/share/nginx/html
- if [[ -x /usr/local/bin/lemper-cli && -d /usr/share/nginx/html/lcp ]]; then
- success "LEMPer CLI & web tools successfully installed."
- fi
+ #if [[ -x /usr/local/bin/lemper-cli && -d /usr/share/nginx/html/lcp ]]; then
+ # success "LEMPer CLI & web tools successfully installed."
+ #fi
}
echo "[LEMPer CLI & Web Tools Installation]"
diff --git a/scripts/install_vsftpd.sh b/scripts/install_vsftpd.sh
index c67c42a0..9dd247e6 100755
--- a/scripts/install_vsftpd.sh
+++ b/scripts/install_vsftpd.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Make sure only supported distribution can run this installer script.
preflight_system_check
@@ -118,7 +118,7 @@ function init_vsftpd_install() {
elif [[ -f "${LIB_GNU_DIR}/libcap.so" ]]; then
run ln -s "${LIB_GNU_DIR}/libcap.so" "${LIB_DIR}/libcap.so"
else
- error "Cannot find libcap.so file."
+ echo "Cannot find libcap.so file."
fi
local CURRENT_DIR && \
@@ -135,11 +135,21 @@ function init_vsftpd_install() {
run cd "${BUILD_DIR}" && \
run wget -q "${VSFTPD_ZIP_URL}" && \
run tar -zxf "${VSFTPD_FILENAME}" && \
- run cd vsftpd-*/ && \
+ run cd vsftpd-*/ || return 1
+
+ # If SSL Enabled, modify the builddefs.h file.
+ if [[ "${VSFTPD_SSL_ENABLE}" == true ]]; then
+ run sed -i 's/\#undef\ VSF_BUILD_SSL/\#define\ VSF_BUILD_SSL/g' ./builddefs.h
+ fi
+
run make && \
run make install && \
run ldconfig /usr/local/lib && \
run cd "${CURRENT_DIR}" || return 1
+
+ # Move executable to /usr/sbin.
+ [ -x /usr/local/sbin/vsftpd ] && \
+ run mv /usr/local/sbin/vsftpd /usr/sbin/
;;
*)
# Skip installation.
@@ -182,9 +192,13 @@ pasv_max_port=50000
user_sub_token=$USER
local_root=/home/$USER
-rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
-rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
-ssl_enable=Yes
+EOL
+
+ # Enable SSL.
+ if [[ "${VSFTPD_SSL_ENABLE}" == true ]]; then
+ cat >> /etc/vsftpd.conf <.
-#
-# This project would not be possible without help from:
-# Matthew Montgomery Paul Kehrer Dave Burgess
-# Jonathan Hinds Mike Jackson Nils Breunese
-# Shawn Ashlee Luuk Vosslamber Ville Skytta
-# Trent Hornibrook Jason Gill Mark Imbriaco
-# Greg Eden Aubin Galinotti Giovanni Bechis
-# Bill Bradford Ryan Novosielski Michael Scheidell
-# Blair Christensen Hans du Plooy Victor Trac
-# Everett Barnes Tom Krouper Gary Barrueto
-# Simon Greenaway Adam Stein Isart Montane
-# Baptiste M. Cole Turner Major Hayden
-# Joe Ashcraft Jean-Marie Renouard
-#
-# Inspired by Matthew Montgomery's tuning-primer.sh script:
-# http://forge.mysql.com/projects/view.php?id=44
-#
-
-# ---------------------------------------------------------------------------
-# BEGIN TEXT TEMPLATE MODULE
-# ---------------------------------------------------------------------------
-# Text::Template.pm
-#
-# Fill in `templates'
-#
-# Copyright 2013 M. J. Dominus.
-# You may copy and distribute this program under the
-# same terms as Perl itself.
-# If in doubt, write to mjd-perl-template+@plover.com for a license.
-#
-# Version 1.46
-
-package Text::Template;
-require 5.004;
-use Exporter;
-#use no strict;
-@ISA = qw(Exporter);
-@EXPORT_OK = qw(fill_in_file fill_in_string TTerror);
-use vars '$ERROR';
-use strict;
-
-$Text::Template::VERSION = '1.46';
-my %GLOBAL_PREPEND = ('Text::Template' => '');
-
-sub Version {
- $Text::Template::VERSION;
-}
-
-sub _param {
- my $kk;
- my ($k, %h) = @_;
- for $kk ($k, "\u$k", "\U$k", "-$k", "-\u$k", "-\U$k") {
- return $h{$kk} if exists $h{$kk};
- }
- return;
-}
-
-sub always_prepend
-{
- my $pack = shift;
- my $old = $GLOBAL_PREPEND{$pack};
- $GLOBAL_PREPEND{$pack} = shift;
- $old;
-}
-
-{
- my %LEGAL_TYPE;
- BEGIN {
- %LEGAL_TYPE = map {$_=>1} qw(FILE FILEHANDLE STRING ARRAY);
- }
- sub new {
- my $pack = shift;
- my %a = @_;
- my $stype = uc(_param('type', %a) || "FILE");
- my $source = _param('source', %a);
- my $untaint = _param('untaint', %a);
- my $prepend = _param('prepend', %a);
- my $alt_delim = _param('delimiters', %a);
- my $broken = _param('broken', %a);
- unless (defined $source) {
- require Carp;
- Carp::croak("Usage: $ {pack}::new(TYPE => ..., SOURCE => ...)");
- }
- unless ($LEGAL_TYPE{$stype}) {
- require Carp;
- Carp::croak("Illegal value `$stype' for TYPE parameter");
- }
- my $self = {TYPE => $stype,
- PREPEND => $prepend,
- UNTAINT => $untaint,
- BROKEN => $broken,
- (defined $alt_delim ? (DELIM => $alt_delim) : ()),
- };
- # Under 5.005_03, if any of $stype, $prepend, $untaint, or $broken
- # are tainted, all the others become tainted too as a result of
- # sharing the expression with them. We install $source separately
- # to prevent it from acquiring a spurious taint.
- $self->{SOURCE} = $source;
-
- bless $self => $pack;
- return unless $self->_acquire_data;
-
- $self;
- }
-}
-
-# Convert template objects of various types to type STRING,
-# in which the template data is embedded in the object itself.
-sub _acquire_data {
- my ($self) = @_;
- my $type = $self->{TYPE};
- if ($type eq 'STRING') {
- # nothing necessary
- } elsif ($type eq 'FILE') {
- my $data = _load_text($self->{SOURCE});
- unless (defined $data) {
- # _load_text already set $ERROR
- return undef;
- }
- if ($self->{UNTAINT} && _is_clean($self->{SOURCE})) {
- _unconditionally_untaint($data);
- }
- $self->{TYPE} = 'STRING';
- $self->{FILENAME} = $self->{SOURCE};
- $self->{SOURCE} = $data;
- } elsif ($type eq 'ARRAY') {
- $self->{TYPE} = 'STRING';
- $self->{SOURCE} = join '', @{$self->{SOURCE}};
- } elsif ($type eq 'FILEHANDLE') {
- $self->{TYPE} = 'STRING';
- local $/;
- my $fh = $self->{SOURCE};
- my $data = <$fh>; # Extra assignment avoids bug in Solaris perl5.00[45].
- if ($self->{UNTAINT}) {
- _unconditionally_untaint($data);
- }
- $self->{SOURCE} = $data;
- } else {
- # This should have been caught long ago, so it represents a
- # drastic `can't-happen' sort of failure
- my $pack = ref $self;
- die "Can only acquire data for $pack objects of subtype STRING, but this is $type; aborting";
- }
- $self->{DATA_ACQUIRED} = 1;
-}
-
-sub source {
- my ($self) = @_;
- $self->_acquire_data unless $self->{DATA_ACQUIRED};
- return $self->{SOURCE};
-}
-
-sub set_source_data {
- my ($self, $newdata) = @_;
- $self->{SOURCE} = $newdata;
- $self->{DATA_ACQUIRED} = 1;
- $self->{TYPE} = 'STRING';
- 1;
-}
-
-sub compile {
- my $self = shift;
-
- return 1 if $self->{TYPE} eq 'PREPARSED';
-
- return undef unless $self->_acquire_data;
- unless ($self->{TYPE} eq 'STRING') {
- my $pack = ref $self;
- # This should have been caught long ago, so it represents a
- # drastic `can't-happen' sort of failure
- die "Can only compile $pack objects of subtype STRING, but this is $self->{TYPE}; aborting";
- }
-
- my @tokens;
- my $delim_pats = shift() || $self->{DELIM};
-
-
-
- my ($t_open, $t_close) = ('{', '}');
- my $DELIM; # Regex matches a delimiter if $delim_pats
- if (defined $delim_pats) {
- ($t_open, $t_close) = @$delim_pats;
- $DELIM = "(?:(?:\Q$t_open\E)|(?:\Q$t_close\E))";
- @tokens = split /($DELIM|\n)/, $self->{SOURCE};
- } else {
- @tokens = split /(\\\\(?=\\*[{}])|\\[{}]|[{}\n])/, $self->{SOURCE};
- }
- my $state = 'TEXT';
- my $depth = 0;
- my $lineno = 1;
- my @content;
- my $cur_item = '';
- my $prog_start;
- while (@tokens) {
- my $t = shift @tokens;
- next if $t eq '';
- if ($t eq $t_open) { # Brace or other opening delimiter
- if ($depth == 0) {
- push @content, [$state, $cur_item, $lineno] if $cur_item ne '';
- $cur_item = '';
- $state = 'PROG';
- $prog_start = $lineno;
- } else {
- $cur_item .= $t;
- }
- $depth++;
- } elsif ($t eq $t_close) { # Brace or other closing delimiter
- $depth--;
- if ($depth < 0) {
- $ERROR = "Unmatched close brace at line $lineno";
- return undef;
- } elsif ($depth == 0) {
- push @content, [$state, $cur_item, $prog_start] if $cur_item ne '';
- $state = 'TEXT';
- $cur_item = '';
- } else {
- $cur_item .= $t;
- }
- } elsif (!$delim_pats && $t eq '\\\\') { # precedes \\\..\\\{ or \\\..\\\}
- $cur_item .= '\\';
- } elsif (!$delim_pats && $t =~ /^\\([{}])$/) { # Escaped (literal) brace?
- $cur_item .= $1;
- } elsif ($t eq "\n") { # Newline
- $lineno++;
- $cur_item .= $t;
- } else { # Anything else
- $cur_item .= $t;
- }
- }
-
- if ($state eq 'PROG') {
- $ERROR = "End of data inside program text that began at line $prog_start";
- return undef;
- } elsif ($state eq 'TEXT') {
- push @content, [$state, $cur_item, $lineno] if $cur_item ne '';
- } else {
- die "Can't happen error #1";
- }
-
- $self->{TYPE} = 'PREPARSED';
- $self->{SOURCE} = \@content;
- 1;
-}
-
-sub prepend_text {
- my ($self) = @_;
- my $t = $self->{PREPEND};
- unless (defined $t) {
- $t = $GLOBAL_PREPEND{ref $self};
- unless (defined $t) {
- $t = $GLOBAL_PREPEND{'Text::Template'};
- }
- }
- $self->{PREPEND} = $_[1] if $#_ >= 1;
- return $t;
-}
-
-sub fill_in {
- my $fi_self = shift;
- my %fi_a = @_;
-
- unless ($fi_self->{TYPE} eq 'PREPARSED') {
- my $delims = _param('delimiters', %fi_a);
- my @delim_arg = (defined $delims ? ($delims) : ());
- $fi_self->compile(@delim_arg)
- or return undef;
- }
-
- my $fi_varhash = _param('hash', %fi_a);
- my $fi_package = _param('package', %fi_a) ;
- my $fi_broken =
- _param('broken', %fi_a) || $fi_self->{BROKEN} || \&_default_broken;
- my $fi_broken_arg = _param('broken_arg', %fi_a) || [];
- my $fi_safe = _param('safe', %fi_a);
- my $fi_ofh = _param('output', %fi_a);
- my $fi_eval_package;
- my $fi_scrub_package = 0;
- my $fi_filename = _param('filename') || $fi_self->{FILENAME} || 'template';
-
- my $fi_prepend = _param('prepend', %fi_a);
- unless (defined $fi_prepend) {
- $fi_prepend = $fi_self->prepend_text;
- }
-
- if (defined $fi_safe) {
- $fi_eval_package = 'main';
- } elsif (defined $fi_package) {
- $fi_eval_package = $fi_package;
- } elsif (defined $fi_varhash) {
- $fi_eval_package = _gensym();
- $fi_scrub_package = 1;
- } else {
- $fi_eval_package = caller;
- }
-
- my $fi_install_package;
- if (defined $fi_varhash) {
- if (defined $fi_package) {
- $fi_install_package = $fi_package;
- } elsif (defined $fi_safe) {
- $fi_install_package = $fi_safe->root;
- } else {
- $fi_install_package = $fi_eval_package; # The gensymmed one
- }
- _install_hash($fi_varhash => $fi_install_package);
- }
-
- if (defined $fi_package && defined $fi_safe) {
- no strict 'refs';
- # Big fat magic here: Fix it so that the user-specified package
- # is the default one available in the safe compartment.
- *{$fi_safe->root . '::'} = \%{$fi_package . '::'}; # LOD
- }
-
- my $fi_r = '';
- my $fi_item;
- foreach $fi_item (@{$fi_self->{SOURCE}}) {
- my ($fi_type, $fi_text, $fi_lineno) = @$fi_item;
- if ($fi_type eq 'TEXT') {
- $fi_self->append_text_to_output(
- text => $fi_text,
- handle => $fi_ofh,
- out => \$fi_r,
- type => $fi_type,
- );
- } elsif ($fi_type eq 'PROG') {
- no strict;
- my $fi_lcomment = "#line $fi_lineno $fi_filename";
- my $fi_progtext =
- "package $fi_eval_package; $fi_prepend;\n$fi_lcomment\n$fi_text;";
- my $fi_res;
- my $fi_eval_err = '';
- if ($fi_safe) {
- $fi_safe->reval(q{undef $OUT});
- $fi_res = $fi_safe->reval($fi_progtext);
- $fi_eval_err = $@;
- my $OUT = $fi_safe->reval('$OUT');
- $fi_res = $OUT if defined $OUT;
- } else {
- my $OUT;
- $fi_res = eval $fi_progtext;
- $fi_eval_err = $@;
- $fi_res = $OUT if defined $OUT;
- }
-
- # If the value of the filled-in text really was undef,
- # change it to an explicit empty string to avoid undefined
- # value warnings later.
- $fi_res = '' unless defined $fi_res;
-
- if ($fi_eval_err) {
- $fi_res = $fi_broken->(text => $fi_text,
- error => $fi_eval_err,
- lineno => $fi_lineno,
- arg => $fi_broken_arg,
- );
- if (defined $fi_res) {
- $fi_self->append_text_to_output(
- text => $fi_res,
- handle => $fi_ofh,
- out => \$fi_r,
- type => $fi_type,
- );
- } else {
- return $fi_res; # Undefined means abort processing
- }
- } else {
- $fi_self->append_text_to_output(
- text => $fi_res,
- handle => $fi_ofh,
- out => \$fi_r,
- type => $fi_type,
- );
- }
- } else {
- die "Can't happen error #2";
- }
- }
-
- _scrubpkg($fi_eval_package) if $fi_scrub_package;
- defined $fi_ofh ? 1 : $fi_r;
-}
-
-sub append_text_to_output {
- my ($self, %arg) = @_;
-
- if (defined $arg{handle}) {
- print { $arg{handle} } $arg{text};
- } else {
- ${ $arg{out} } .= $arg{text};
- }
-
- return;
-}
-
-sub fill_this_in {
- my $pack = shift;
- my $text = shift;
- my $templ = $pack->new(TYPE => 'STRING', SOURCE => $text, @_)
- or return undef;
- $templ->compile or return undef;
- my $result = $templ->fill_in(@_);
- $result;
-}
-
-sub fill_in_string {
- my $string = shift;
- my $package = _param('package', @_);
- push @_, 'package' => scalar(caller) unless defined $package;
- Text::Template->fill_this_in($string, @_);
-}
-
-sub fill_in_file {
- my $fn = shift;
- my $templ = Text::Template->new(TYPE => 'FILE', SOURCE => $fn, @_)
- or return undef;
- $templ->compile or return undef;
- my $text = $templ->fill_in(@_);
- $text;
-}
-
-sub _default_broken {
- my %a = @_;
- my $prog_text = $a{text};
- my $err = $a{error};
- my $lineno = $a{lineno};
- chomp $err;
-# $err =~ s/\s+at .*//s;
- "Program fragment delivered error ``$err''";
-}
-
-sub _load_text {
- my $fn = shift;
- local *F;
- unless (open F, $fn) {
- $ERROR = "Couldn't open file $fn: $!";
- return undef;
- }
- local $/;
- ;
-}
-
-sub _is_clean {
- my $z;
- eval { ($z = join('', @_)), eval '#' . substr($z,0,0); 1 } # LOD
-}
-
-sub _unconditionally_untaint {
- for (@_) {
- ($_) = /(.*)/s;
- }
-}
-
-{
- my $seqno = 0;
- sub _gensym {
- __PACKAGE__ . '::GEN' . $seqno++;
- }
- sub _scrubpkg {
- my $s = shift;
- $s =~ s/^Text::Template:://;
- no strict 'refs';
- my $hash = $Text::Template::{$s."::"};
- foreach my $key (keys %$hash) {
- undef $hash->{$key};
- }
- }
-}
-
-# Given a hashful of variables (or a list of such hashes)
-# install the variables into the specified package,
-# overwriting whatever variables were there before.
-sub _install_hash {
- my $hashlist = shift;
- my $dest = shift;
- if (UNIVERSAL::isa($hashlist, 'HASH')) {
- $hashlist = [$hashlist];
- }
- my $hash;
- foreach $hash (@$hashlist) {
- my $name;
- foreach $name (keys %$hash) {
- my $val = $hash->{$name};
- no strict 'refs';
- local *SYM = *{"$ {dest}::$name"};
- if (! defined $val) {
- delete ${"$ {dest}::"}{$name};
- } elsif (ref $val) {
- *SYM = $val;
- } else {
- *SYM = \$val;
- }
- }
- }
-}
-
-sub TTerror { $ERROR }
-
-1;
-# ---------------------------------------------------------------------------
-# END TEXT TEMPLATE MODULE
-# ---------------------------------------------------------------------------
-
-
-package main;
-use strict;
-use warnings;
-use diagnostics;
-use File::Spec;
-use Getopt::Long;
-use File::Basename;
-use Cwd 'abs_path';
-
-# Set up a few variables for use in the script
-my $tunerversion = "1.6.0";
-my ( @adjvars, @generalrec );
-
-# Set defaults
-my %opt = (
- "silent" => 0,
- "nobad" => 0,
- "nogood" => 0,
- "noinfo" => 0,
- "debug" => 0,
- "nocolor" => 0,
- "forcemem" => 0,
- "forceswap" => 0,
- "host" => 0,
- "socket" => 0,
- "port" => 0,
- "user" => 0,
- "pass" => 0,
- "skipsize" => 0,
- "checkversion" => 0,
- "buffers" => 0,
- "passwordfile" => 0,
- "outputfile" => 0,
- "dbstat" => 0,
- "idxstat" => 0,
- "skippassword" => 0,
- "noask" => 0,
- "template" => 0,
- "reportfile" => 0
-);
-
-# Gather the options from the command line
-GetOptions(
- \%opt, 'nobad', 'nogood', 'noinfo',
- 'debug', 'nocolor', 'forcemem=i', 'forceswap=i',
- 'host=s', 'socket=s', 'port=i', 'user=s',
- 'pass=s', 'skipsize', 'checkversion', 'mysqladmin=s',
- 'mysqlcmd=s', 'help', 'buffers', 'skippassword',
- 'passwordfile=s', 'outputfile=s', 'silent', 'dbstat',
- 'idxstat', 'noask', 'template=s', 'reportfile=s'
-);
-
-if ( defined $opt{'help'} && $opt{'help'} == 1 ) { usage(); }
-
-sub usage {
-
- # Shown with --help option passed
- print " MySQLTuner $tunerversion - MySQL High Performance Tuning Script\n"
- . " Bug reports, feature requests, and downloads at http://mysqltuner.com/\n"
- . " Maintained by Major Hayden (major\@mhtx.net) - Licensed under GPL\n"
- . "\n"
- . " Important Usage Guidelines:\n"
- . " To run the script with the default options, run the script without arguments\n"
- . " Allow MySQL server to run for at least 24-48 hours before trusting suggestions\n"
- . " Some routines may require root level privileges (script will provide warnings)\n"
- . " You must provide the remote server's total memory when connecting to other servers\n"
- . "\n"
- . " Connection and Authentication\n"
- . " --host Connect to a remote host to perform tests (default: localhost)\n"
- . " --socket Use a different socket for a local connection\n"
- . " --port Port to use for connection (default: 3306)\n"
- . " --user Username to use for authentication\n"
- . " --pass Password to use for authentication\n"
- . " --mysqladmin Path to a custom mysqladmin executable\n"
- . " --mysqlcmd Path to a custom mysql executable\n" . "\n"
- . " --noask Dont ask password if needed\n" . "\n"
- . " Performance and Reporting Options\n"
- . " --skipsize Don't enumerate tables and their types/sizes (default: on)\n"
- . " (Recommended for servers with many tables)\n"
- . " --skippassword Don't perform checks on user passwords(default: off)\n"
- . " --checkversion Check for updates to MySQLTuner (default: don't check)\n"
- . " --forcemem Amount of RAM installed in megabytes\n"
- . " --forceswap Amount of swap memory configured in megabytes\n"
- . " --passwordfile Path to a password file list(one password by line)\n"
- . " Output Options:\n"
- . " --silent Don't output anything on screen\n"
- . " --nogood Remove OK responses\n"
- . " --nobad Remove negative/suggestion responses\n"
- . " --noinfo Remove informational responses\n"
- . " --debug Print debug information\n"
- . " --dbstat Print database information\n"
- . " --idxstat Print index information\n"
- . " --nocolor Don't print output in color\n"
- . " --buffers Print global and per-thread buffer values\n"
- . " --outputfile Path to a output txt file\n" . "\n"
- . " --reportfile Path to a report txt file\n" . "\n"
- . " --template Path to a template file\n" . "\n";
- exit 0;
-}
-
-my $devnull = File::Spec->devnull();
-my $basic_password_files =
- ( $opt{passwordfile} eq "0" )
- ? abs_path( dirname(__FILE__) ) . "/basic_passwords.txt"
- : abs_path( $opt{passwordfile} );
-
-# for RPM distributions
-$basic_password_files = "/usr/share/mysqltuner/basic_passwords.txt"
- unless -f "$basic_password_files";
-
-#
-my $outputfile = undef;
-$outputfile = abs_path( $opt{outputfile} ) unless $opt{outputfile} eq "0";
-
-my $fh = undef;
-open( $fh, '>', $outputfile )
- or die("Fail opening $outputfile")
- if defined($outputfile);
-$opt{nocolor} = 1 if defined($outputfile);
-
-# Setting up the colors for the print styles
-my $good = ( $opt{nocolor} == 0 ) ? "[\e[0;32mOK\e[0m]" : "[OK]";
-my $bad = ( $opt{nocolor} == 0 ) ? "[\e[0;31m!!\e[0m]" : "[!!]";
-my $info = ( $opt{nocolor} == 0 ) ? "[\e[0;34m--\e[0m]" : "[--]";
-my $deb = ( $opt{nocolor} == 0 ) ? "[\e[0;31mDG\e[0m]" : "[DG]";
-
-# Super sturucture containing all informations
-my %result;
-
-# Functions that handle the print styles
-sub prettyprint {
- print $_[0] . "\n" unless $opt{'silent'};
- print $fh $_[0] . "\n" if defined($fh);
-}
-sub goodprint { prettyprint $good. " " . $_[0] unless ( $opt{nogood} == 1 ); }
-sub infoprint { prettyprint $info. " " . $_[0] unless ( $opt{noinfo} == 1 ); }
-sub badprint { prettyprint $bad. " " . $_[0] unless ( $opt{nobad} == 1 ); }
-sub debugprint { prettyprint $deb. " " . $_[0] unless ( $opt{debug} == 0 ); }
-sub redwrap {
- return ( $opt{nocolor} == 0 ) ? "\e[0;31m" . $_[0] . "\e[0m" : $_[0];
-}
-
-sub greenwrap {
- return ( $opt{nocolor} == 0 ) ? "\e[0;32m" . $_[0] . "\e[0m" : $_[0];
-}
-
-# Calculates the parameter passed in bytes, and then rounds it to one decimal place
-sub hr_bytes {
- my $num = shift;
- if ( $num >= ( 1024**3 ) ) { #GB
- return sprintf( "%.1f", ( $num / ( 1024**3 ) ) ) . "G";
- }
- elsif ( $num >= ( 1024**2 ) ) { #MB
- return sprintf( "%.1f", ( $num / ( 1024**2 ) ) ) . "M";
- }
- elsif ( $num >= 1024 ) { #KB
- return sprintf( "%.1f", ( $num / 1024 ) ) . "K";
- }
- else {
- return $num . "B";
- }
-}
-
-# Calculates the parameter passed in bytes, and then rounds it to the nearest integer
-sub hr_bytes_rnd {
- my $num = shift;
- if ( $num >= ( 1024**3 ) ) { #GB
- return int( ( $num / ( 1024**3 ) ) ) . "G";
- }
- elsif ( $num >= ( 1024**2 ) ) { #MB
- return int( ( $num / ( 1024**2 ) ) ) . "M";
- }
- elsif ( $num >= 1024 ) { #KB
- return int( ( $num / 1024 ) ) . "K";
- }
- else {
- return $num . "B";
- }
-}
-
-# Calculates the parameter passed to the nearest power of 1000, then rounds it to the nearest integer
-sub hr_num {
- my $num = shift;
- if ( $num >= ( 1000**3 ) ) { # Billions
- return int( ( $num / ( 1000**3 ) ) ) . "B";
- }
- elsif ( $num >= ( 1000**2 ) ) { # Millions
- return int( ( $num / ( 1000**2 ) ) ) . "M";
- }
- elsif ( $num >= 1000 ) { # Thousands
- return int( ( $num / 1000 ) ) . "K";
- }
- else {
- return $num;
- }
-}
-
-# Calculate Percentage
-sub percentage {
- my $value = shift;
- my $total = shift;
- $total = 0 unless defined $total;
- return 100, 00 if $total == 0;
- return sprintf( "%.2f", ( $value * 100 / $total ) );
-}
-
-# Calculates uptime to display in a more attractive form
-sub pretty_uptime {
- my $uptime = shift;
- my $seconds = $uptime % 60;
- my $minutes = int( ( $uptime % 3600 ) / 60 );
- my $hours = int( ( $uptime % 86400 ) / (3600) );
- my $days = int( $uptime / (86400) );
- my $uptimestring;
- if ( $days > 0 ) {
- $uptimestring = "${days}d ${hours}h ${minutes}m ${seconds}s";
- }
- elsif ( $hours > 0 ) {
- $uptimestring = "${hours}h ${minutes}m ${seconds}s";
- }
- elsif ( $minutes > 0 ) {
- $uptimestring = "${minutes}m ${seconds}s";
- }
- else {
- $uptimestring = "${seconds}s";
- }
- return $uptimestring;
-}
-
-# Retrieves the memory installed on this machine
-my ( $physical_memory, $swap_memory, $duflags );
-
-sub os_setup {
-
- sub memerror {
- badprint
-"Unable to determine total memory/swap; use '--forcemem' and '--forceswap'";
- exit 1;
- }
- my $os = `uname`;
- $duflags = ( $os =~ /Linux/ ) ? '-b' : '';
- if ( $opt{'forcemem'} > 0 ) {
- $physical_memory = $opt{'forcemem'} * 1048576;
- infoprint "Assuming $opt{'forcemem'} MB of physical memory";
- if ( $opt{'forceswap'} > 0 ) {
- $swap_memory = $opt{'forceswap'} * 1048576;
- infoprint "Assuming $opt{'forceswap'} MB of swap space";
- }
- else {
- $swap_memory = 0;
- badprint
- "Assuming 0 MB of swap space (use --forceswap to specify)";
- }
- }
- else {
- if ( $os =~ /Linux/ ) {
- $physical_memory =
- `grep -i memtotal: /proc/meminfo | awk '{print \$2}'`
- or memerror;
- $physical_memory *= 1024;
-
- $swap_memory =
- `grep -i swaptotal: /proc/meminfo | awk '{print \$2}'`
- or memerror;
- $swap_memory *= 1024;
- }
- elsif ( $os =~ /Darwin/ ) {
- $physical_memory = `sysctl -n hw.memsize` or memerror;
- $swap_memory =
- `sysctl -n vm.swapusage | awk '{print \$3}' | sed 's/\..*\$//'`
- or memerror;
- }
- elsif ( $os =~ /NetBSD|OpenBSD|FreeBSD/ ) {
- $physical_memory = `sysctl -n hw.physmem` or memerror;
- if ( $physical_memory < 0 ) {
- $physical_memory = `sysctl -n hw.physmem64` or memerror;
- }
- $swap_memory =
- `swapctl -l | grep '^/' | awk '{ s+= \$2 } END { print s }'`
- or memerror;
- }
- elsif ( $os =~ /BSD/ ) {
- $physical_memory = `sysctl -n hw.realmem` or memerror;
- $swap_memory =
- `swapinfo | grep '^/' | awk '{ s+= \$2 } END { print s }'`;
- }
- elsif ( $os =~ /SunOS/ ) {
- $physical_memory =
- `/usr/sbin/prtconf | grep Memory | cut -f 3 -d ' '`
- or memerror;
- chomp($physical_memory);
- $physical_memory = $physical_memory * 1024 * 1024;
- }
- elsif ( $os =~ /AIX/ ) {
- $physical_memory =
- `lsattr -El sys0 | grep realmem | awk '{print \$2}'`
- or memerror;
- chomp($physical_memory);
- $physical_memory = $physical_memory * 1024;
- $swap_memory = `lsps -as | awk -F"(MB| +)" '/MB /{print \$2}'`
- or memerror;
- chomp($swap_memory);
- $swap_memory = $swap_memory * 1024 * 1024;
- }
- }
- debugprint "Physical Memory: $physical_memory";
- debugprint "Swap Memory: $swap_memory";
- chomp($physical_memory);
- chomp($swap_memory);
- chomp($os);
- $result{'OS'}{'OS Type'} = $os;
- $result{'OS'}{'Physical Memory'}{'bytes'} = $physical_memory;
- $result{'OS'}{'Physical Memory'}{'pretty'} = hr_bytes($physical_memory);
- $result{'OS'}{'Swap Memory'}{'bytes'} = $swap_memory;
- $result{'OS'}{'Swap Memory'}{'pretty'} = hr_bytes($swap_memory);
-
-}
-
-# Checks for updates to MySQLTuner
-sub validate_tuner_version {
- if ($opt{checkversion} eq 0) {
- infoprint "Skipped version check for MySQLTuner script";
- return;
- }
-
- my $update;
- my $url = "https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl";
- my $httpcli=`which curl`;
- chomp($httpcli);
- if ( 1 != 1 and defined($httpcli) and -e "$httpcli" ) {
- debugprint "$httpcli is available.";
-
- debugprint "$httpcli --connect-timeout 5 -silent '$url' 2>/dev/null | grep 'my \$tunerversion'| cut -d\\\" -f2";
- $update = `$httpcli --connect-timeout 5 -silent '$url' 2>/dev/null | grep 'my \$tunerversion'| cut -d\\\" -f2`;
- chomp($update);
- debugprint "VERSION: $update";
-
-
- compare_tuner_version($update);
- return;
- }
-
-
- $httpcli=`which wget`;
- chomp($httpcli);
- if ( defined($httpcli) and -e "$httpcli" ) {
- debugprint "$httpcli is available.";
-
- debugprint "$httpcli -e timestamping=off -T 5 -O - '$url' 2>$devnull| grep 'my \$tunerversion'| cut -d\\\" -f2";
- $update = `$httpcli -e timestamping=off -T 5 -O - '$url' 2>$devnull| grep 'my \$tunerversion'| cut -d\\\" -f2`;
- chomp($update);
- compare_tuner_version($update);
- return;
- }
- debugprint "curl and wget are not avalaible.";
- infoprint "Unable to check for the latest MySQLTuner version";
-}
-
-sub compare_tuner_version {
- my $remoteversion=shift;
- debugprint "Remote data: $remoteversion";
- #exit 0;
- if ($remoteversion ne $tunerversion) {
- badprint "There is a new version of MySQLTuner available ($remoteversion)";
- return;
- }
- goodprint "You have the latest version of MySQLTuner($tunerversion)";
- return;
-}
-
-# Checks to see if a MySQL login is possible
-my ( $mysqllogin, $doremote, $remotestring, $mysqlcmd, $mysqladmincmd );
-
-sub mysql_setup {
- $doremote = 0;
- $remotestring = '';
- if ( $opt{mysqladmin} ) {
- $mysqladmincmd = $opt{mysqladmin};
- }
- else {
- $mysqladmincmd = `which mysqladmin`;
- }
- chomp($mysqladmincmd);
- if ( !-e $mysqladmincmd && $opt{mysqladmin} ) {
- badprint "Unable to find the mysqladmin command you specified: "
- . $mysqladmincmd . "";
- exit 1;
- }
- elsif ( !-e $mysqladmincmd ) {
- badprint
- "Couldn't find mysqladmin in your \$PATH. Is MySQL installed?";
- exit 1;
- }
- if ( $opt{mysqlcmd} ) {
- $mysqlcmd = $opt{mysqlcmd};
- }
- else {
- $mysqlcmd = `which mysql`;
- }
- chomp($mysqlcmd);
- if ( !-e $mysqlcmd && $opt{mysqlcmd} ) {
- badprint "Unable to find the mysql command you specified: "
- . $mysqlcmd . "";
- exit 1;
- }
- elsif ( !-e $mysqlcmd ) {
- badprint "Couldn't find mysql in your \$PATH. Is MySQL installed?";
- exit 1;
- }
- $mysqlcmd =~ s/\n$//g;
- my $mysqlclidefaults=`$mysqlcmd --print-defaults`;
- debugprint "MySQL Client: $mysqlclidefaults";
- if ( $mysqlclidefaults=~/auto-vertical-output/ ) {
- badprint "Avoid auto-vertical-output in configuration file(s) for MySQL like";
- exit 1;
- }
-
- debugprint "MySQL Client: $mysqlcmd";
-
- # Are we being asked to connect via a socket?
- if ( $opt{socket} ne 0 ) {
- $remotestring = " -S $opt{socket}";
- }
-
- # Are we being asked to connect to a remote server?
- if ( $opt{host} ne 0 ) {
- chomp( $opt{host} );
- $opt{port} = ( $opt{port} eq 0 ) ? 3306 : $opt{port};
-
- # If we're doing a remote connection, but forcemem wasn't specified, we need to exit
- if ( $opt{'forcemem'} eq 0 ) {
- badprint
- "The --forcemem option is required for remote connections";
- exit 1;
- }
- infoprint "Performing tests on $opt{host}:$opt{port}";
- $remotestring = " -h $opt{host} -P $opt{port}";
- $doremote = 1;
- }
-
- # Did we already get a username and password passed on the command line?
- if ( $opt{user} ne 0 and $opt{pass} ne 0 ) {
- $mysqllogin = "-u $opt{user} -p'$opt{pass}'" . $remotestring;
- my $loginstatus = `$mysqladmincmd ping $mysqllogin 2>&1`;
- if ( $loginstatus =~ /mysqld is alive/ ) {
- goodprint
- "Logged in using credentials passed on the command line";
- return 1;
- }
- else {
- badprint
- "Attempted to use login credentials, but they were invalid";
- exit 1;
- }
- }
- my $svcprop = `which svcprop 2>/dev/null`;
- if ( substr( $svcprop, 0, 1 ) =~ "/" ) {
-
- # We are on solaris
- ( my $mysql_login =
-`svcprop -p quickbackup/username svc:/network/mysql-quickbackup:default`
- ) =~ s/\s+$//;
- ( my $mysql_pass =
-`svcprop -p quickbackup/password svc:/network/mysql-quickbackup:default`
- ) =~ s/\s+$//;
- if ( substr( $mysql_login, 0, 7 ) ne "svcprop" ) {
-
- # mysql-quickbackup is installed
- $mysqllogin = "-u $mysql_login -p$mysql_pass";
- my $loginstatus = `mysqladmin $mysqllogin ping 2>&1`;
- if ( $loginstatus =~ /mysqld is alive/ ) {
- goodprint
- "Logged in using credentials from mysql-quickbackup.";
- return 1;
- }
- else {
- badprint
-"Attempted to use login credentials from mysql-quickbackup, but they failed.";
- exit 1;
- }
- }
- }
- elsif ( -r "/etc/psa/.psa.shadow" and $doremote == 0 ) {
-
- # It's a Plesk box, use the available credentials
- $mysqllogin = "-u admin -p`cat /etc/psa/.psa.shadow`";
- my $loginstatus = `$mysqladmincmd ping $mysqllogin 2>&1`;
- unless ( $loginstatus =~ /mysqld is alive/ ) {
- badprint
-"Attempted to use login credentials from Plesk, but they failed.";
- exit 1;
- }
- }
- elsif ( -r "/usr/local/directadmin/conf/mysql.conf" and $doremote == 0 ) {
-
- # It's a DirectAdmin box, use the available credentials
- my $mysqluser =
- `cat /usr/local/directadmin/conf/mysql.conf | egrep '^user=.*'`;
- my $mysqlpass =
- `cat /usr/local/directadmin/conf/mysql.conf | egrep '^passwd=.*'`;
-
- $mysqluser =~ s/user=//;
- $mysqluser =~ s/[\r\n]//;
- $mysqlpass =~ s/passwd=//;
- $mysqlpass =~ s/[\r\n]//;
-
- $mysqllogin = "-u $mysqluser -p$mysqlpass";
-
- my $loginstatus = `mysqladmin ping $mysqllogin 2>&1`;
- unless ( $loginstatus =~ /mysqld is alive/ ) {
- badprint
-"Attempted to use login credentials from DirectAdmin, but they failed.";
- exit 1;
- }
- }
- elsif ( -r "/etc/mysql/debian.cnf" and $doremote == 0 ) {
-
- # We have a debian maintenance account, use it
- $mysqllogin = "--defaults-file=/etc/mysql/debian.cnf";
- my $loginstatus = `$mysqladmincmd $mysqllogin ping 2>&1`;
- if ( $loginstatus =~ /mysqld is alive/ ) {
- goodprint
- "Logged in using credentials from debian maintenance account.";
- return 1;
- }
- else {
- badprint
-"Attempted to use login credentials from debian maintenance account, but they failed.";
- exit 1;
- }
- }
- else {
-
- # It's not Plesk or debian, we should try a login
- debugprint "$mysqladmincmd $remotestring ping 2>&1";
- my $loginstatus = `$mysqladmincmd $remotestring ping 2>&1`;
- if ( $loginstatus =~ /mysqld is alive/ ) {
-
- # Login went just fine
- $mysqllogin = " $remotestring ";
-
- # Did this go well because of a .my.cnf file or is there no password set?
- my $userpath = `printenv HOME`;
- if ( length($userpath) > 0 ) {
- chomp($userpath);
- }
- unless ( -e "${userpath}/.my.cnf" or -e "${userpath}/.mylogin.cnf" )
- {
- badprint
-"Successfully authenticated with no password - SECURITY RISK!";
- }
- return 1;
- }
- else {
- if ( $opt{'noask'}==1 ) {
- badprint "Attempted to use login credentials, but they were invalid";
- exit 1;
- }
-
- print STDERR "Please enter your MySQL administrative login: ";
- my $name = <>;
- print STDERR "Please enter your MySQL administrative password: ";
- system("stty -echo >$devnull 2>&1");
- my $password = <>;
- system("stty echo >$devnull 2>&1");
- chomp($password);
- chomp($name);
- $mysqllogin = "-u $name";
-
- if ( length($password) > 0 ) {
- $mysqllogin .= " -p'$password'";
- }
- $mysqllogin .= $remotestring;
- my $loginstatus = `$mysqladmincmd ping $mysqllogin 2>&1`;
- if ( $loginstatus =~ /mysqld is alive/ ) {
- print STDERR "";
- if ( !length($password) ) {
-
- # Did this go well because of a .my.cnf file or is there no password set?
- my $userpath = `ls -d ~`;
- chomp($userpath);
- unless ( -e "$userpath/.my.cnf" ) {
- badprint
-"Successfully authenticated with no password - SECURITY RISK!";
- }
- }
- return 1;
- }
- else {
- badprint " Attempted to use login credentials, but they were invalid.";
- exit 1;
- }
- exit 1;
- }
- }
-}
-
-# MySQL Request Array
-sub select_array {
- my $req = shift;
- debugprint "PERFORM: $req ";
- my @result = `$mysqlcmd $mysqllogin -Bse "$req"`;
- chomp(@result);
- return @result;
-}
-
-# MySQL Request one
-sub select_one {
- my $req = shift;
- debugprint "PERFORM: $req ";
- my $result = `$mysqlcmd $mysqllogin -Bse "$req"`;
- chomp($result);
- return $result;
-}
-
-sub get_tuning_info {
- my @infoconn = select_array "\\s";
- my ( $tkey, $tval );
- @infoconn =
- grep { !/Threads:/ and !/Connection id:/ and !/pager:/ and !/Using/ }
- @infoconn;
- foreach my $line (@infoconn) {
- if ( $line =~ /\s*(.*):\s*(.*)/ ) {
- debugprint "$1 => $2";
- $tkey = $1;
- $tval = $2;
- chomp($tkey);
- chomp($tval);
- $result{'MySQL Client'}{$tkey} = $tval;
- }
- }
- $result{'MySQL Client'}{'Client Path'} = $mysqlcmd;
- $result{'MySQL Client'}{'Admin Path'} = $mysqladmincmd;
- $result{'MySQL Client'}{'Authentication Info'} = $mysqllogin;
-
-}
-
-# Populates all of the variable and status hashes
-my ( %mystat, %myvar, $dummyselect, %myrepl, %myslaves );
-
-sub get_all_vars {
-
- # We need to initiate at least one query so that our data is useable
- $dummyselect = select_one "SELECT VERSION()";
- debugprint "VERSION: " . $dummyselect . "";
- $result{'MySQL Client'}{'Version'} = $dummyselect;
- my @mysqlvarlist = select_array "SHOW /*!50000 GLOBAL */ VARIABLES";
- foreach my $line (@mysqlvarlist) {
- $line =~ /([a-zA-Z_]*)\s*(.*)/;
- $myvar{$1} = $2;
- $result{'Variables'}{$1} = $2;
- debugprint "V: $1 = $2";
- }
-
- my @mysqlstatlist = select_array "SHOW /*!50000 GLOBAL */ STATUS";
- foreach my $line (@mysqlstatlist) {
- $line =~ /([a-zA-Z_]*)\s*(.*)/;
- $mystat{$1} = $2;
- $result{'Status'}{$1} = $2;
- debugprint "S: $1 = $2";
- }
-
- # Workaround for MySQL bug #59393 wrt. ignore-builtin-innodb
- if ( ( $myvar{'ignore_builtin_innodb'} || "" ) eq "ON" ) {
- $myvar{'have_innodb'} = "NO";
- }
-
- # have_* for engines is deprecated and will be removed in MySQL 5.6;
- # check SHOW ENGINES and set corresponding old style variables.
- # Also works around MySQL bug #59393 wrt. skip-innodb
- my @mysqlenginelist = select_array "SHOW ENGINES";
- foreach my $line (@mysqlenginelist) {
- if ( $line =~ /^([a-zA-Z_]+)\s+(\S+)/ ) {
- my $engine = lc($1);
-
- if ( $engine eq "federated" || $engine eq "blackhole" ) {
- $engine .= "_engine";
- }
- elsif ( $engine eq "berkeleydb" ) {
- $engine = "bdb";
- }
- my $val = ( $2 eq "DEFAULT" ) ? "YES" : $2;
- $myvar{"have_$engine"} = $val;
- $result{'Storage Engines'}{$engine} = $2;
- }
- }
-
- my @mysqlslave = select_array "SHOW SLAVE STATUS\\G";
-
- foreach my $line (@mysqlslave) {
- if ( $line =~ /\s*(.*):\s*(.*)/ ) {
- debugprint "$1 => $2";
- $myrepl{"$1"} = $2;
- $result{'Replication'}{'Status'}{$1} = $2;
- }
- }
-
- #print Dumper(%myrepl);
- #exit 0;
- my @mysqlslaves = select_array "SHOW SLAVE HOSTS";
- my @lineitems = ();
- foreach my $line (@mysqlslaves) {
- debugprint "L: $line ";
- @lineitems = split /\s+/, $line;
- $myslaves{ $lineitems[0] } = $line;
- $result{'Replication'}{'Slaves'}{ $lineitems[0] } = $lineitems[4];
- }
-}
-
-sub get_basic_passwords {
- my $file = shift;
- open( FH, "< $file" ) or die "Can't open $file for read: $!";
- my @lines = ;
- close FH or die "Cannot close $file: $!";
- return @lines;
-}
-
-sub security_recommendations {
- prettyprint
-"\n-------- Security Recommendations -------------------------------------------";
- if ( $opt{skippassword} eq 1 ) {
- infoprint "Skipped due to --skippassword option";
- return;
- }
-
- # Looking for Anonymous users
- my @mysqlstatlist = select_array
-"SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE TRIM(USER) = '' OR USER IS NULL";
- if (@mysqlstatlist) {
- foreach my $line ( sort @mysqlstatlist ) {
- chomp($line);
- badprint "User '" . $line . "' is an anonymous account.";
- }
- push( @generalrec,
- "Remove Anonymous User accounts - there are "
- . scalar(@mysqlstatlist)
- . " Anonymous accounts." );
- }
- else {
- goodprint "There is no anonymous account in all database users";
- }
-
- # Looking for Empty Password
- @mysqlstatlist = select_array
-"SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE password = '' OR password IS NULL";
- if (@mysqlstatlist) {
- foreach my $line ( sort @mysqlstatlist ) {
- chomp($line);
- badprint "User '" . $line . "' has no password set.";
- }
- push( @generalrec,
-"Set up a Password for user with the following SQL statement ( SET PASSWORD FOR 'user'\@'SpecificDNSorIp' = PASSWORD('secure_password'); )"
- );
- }
- else {
- goodprint "All database users have passwords assigned";
- }
-
- # Looking for User with user/ uppercase /capitalise user as password
- @mysqlstatlist = select_array
-"SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE CAST(password as Binary) = PASSWORD(user) OR CAST(password as Binary) = PASSWORD(UPPER(user)) OR CAST(password as Binary) = PASSWORD(UPPER(LEFT(User, 1)) + SUBSTRING(User, 2, LENGTH(User)))";
- if (@mysqlstatlist) {
- foreach my $line ( sort @mysqlstatlist ) {
- chomp($line);
- badprint "User '" . $line . "' has user name as password.";
- }
- push( @generalrec,
-"Set up a Secure Password for user\@host ( SET PASSWORD FOR 'user'\@'SpecificDNSorIp' = PASSWORD('secure_password'); )"
- );
- }
-
- @mysqlstatlist = select_array
- "SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE HOST='%'";
- if (@mysqlstatlist) {
- foreach my $line ( sort @mysqlstatlist ) {
- chomp($line);
- badprint "User '" . $line . "' hasn't specific host restriction.";
- }
- push( @generalrec,
- "Restrict Host for user\@% to user\@SpecificDNSorIp" );
- }
-
- unless ( -f $basic_password_files ) {
- badprint "There is not basic password file list !";
- return;
- }
-
- my @passwords = get_basic_passwords $basic_password_files;
- infoprint "There is "
- . scalar(@passwords)
- . " basic passwords in the list.";
- my $nbins = 0;
- my $passreq;
- if (@passwords) {
- foreach my $pass (@passwords) {
- $pass =~ s/\s//g;
- chomp($pass);
-
- # Looking for User with user/ uppercase /capitalise weak password
- @mysqlstatlist =
- select_array
-"SELECT CONCAT(user, '\@', host) FROM mysql.user WHERE password = PASSWORD('"
- . $pass
- . "') OR password = PASSWORD(UPPER('"
- . $pass
- . "')) OR password = PASSWORD(UPPER(LEFT('"
- . $pass
- . "', 1)) + SUBSTRING('"
- . $pass
- . "', 2, LENGTH('"
- . $pass . "')))";
- debugprint "There is " . scalar(@mysqlstatlist) . " items.";
- if (@mysqlstatlist) {
- foreach my $line (@mysqlstatlist) {
- chomp($line);
- badprint "User '" . $line
- . "' is using weak pasword: $pass in a lower, upper or capitalize derivated version.";
- $nbins++;
- }
- }
- }
- }
- if ( $nbins > 0 ) {
- push( @generalrec, $nbins . " user(s) used basic or weaked password." );
- }
-}
-
-sub get_replication_status {
- prettyprint
-"\n-------- Replication Metrics -------------------------------------------------";
-
- if ( scalar( keys %myslaves ) == 0 ) {
- infoprint "No replication slave(s) for this server.";
- }
- else {
- infoprint "This server is acting as master for "
- . scalar( keys %myslaves )
- . " server(s).";
- }
-
- if ( scalar( keys %myrepl ) == 0 and scalar( keys %myslaves ) == 0 ) {
- infoprint "This is a standalone server..";
- return;
- }
- if ( scalar( keys %myrepl ) == 0 ) {
- infoprint "No replication setup for this server.";
- return;
- }
- my ($io_running) = $myrepl{'Slave_IO_Running'};
- debugprint "IO RUNNING: $io_running ";
- my ($sql_running) = $myrepl{'Slave_SQL_Running'};
- debugprint "SQL RUNNING: $sql_running ";
- my ($seconds_behind_master) = $myrepl{'Seconds_Behind_Master'};
- debugprint "SECONDS : $seconds_behind_master ";
-
- if ( defined($io_running)
- and ( $io_running !~ /yes/i or $sql_running !~ /yes/i ) )
- {
- badprint
-"This replication slave is not running but seems to be configurated.";
- }
- if ( defined($io_running)
- && $io_running =~ /yes/i
- && $sql_running =~ /yes/i )
- {
- if ( $myvar{'read_only'} eq 'OFF' ) {
- badprint
-"This replication slave is running with the read_only option disabled.";
- }
- else {
- goodprint
-"This replication slave is running with the read_only option enabled.";
- }
- if ( $seconds_behind_master > 0 ) {
- badprint
-"This replication slave is lagging and slave has $seconds_behind_master second(s) behind master host.";
- }
- else {
- goodprint "This replication slave is uptodate with master.";
- }
- }
-}
-
-# Checks for supported or EOL'ed MySQL versions
-my ( $mysqlvermajor, $mysqlverminor, $mysqlvermicro );
-
-sub validate_mysql_version {
- ( $mysqlvermajor, $mysqlverminor, $mysqlvermicro ) =
- $myvar{'version'} =~ /^(\d+)(?:\.(\d+)|)(?:\.(\d+)|)/;
- $mysqlverminor ||= 0;
- $mysqlvermicro ||= 0;
- if ( !mysql_version_ge( 5, 1 ) ) {
- badprint "Your MySQL version "
- . $myvar{'version'}
- . " is EOL software! Upgrade soon!";
- }
- elsif ( ( mysql_version_ge(6) and mysql_version_le(9) ) or mysql_version_ge(12) ) {
- badprint "Currently running unsupported MySQL version "
- . $myvar{'version'} . "";
- } else {
- goodprint "Currently running supported MySQL version "
- . $myvar{'version'} . "";
- }
-}
-
-# Checks if MySQL version is greater than equal to (major, minor, micro)
-sub mysql_version_ge {
- my ( $maj, $min, $mic ) = @_;
- $min ||= 0;
- $mic ||= 0;
- return $mysqlvermajor > $maj
- || $mysqlvermajor == $maj
- && ( $mysqlverminor > $min
- || $mysqlverminor == $min && $mysqlvermicro >= $mic );
-}
-
-# Checks if MySQL version is lower than equal to (major, minor, micro)
-sub mysql_version_le {
- my ( $maj, $min, $mic ) = @_;
- $min ||= 0;
- $mic ||= 0;
- return $mysqlvermajor < $maj
- || $mysqlvermajor == $maj
- && ( $mysqlverminor < $min
- || $mysqlverminor == $min && $mysqlvermicro <= $mic );
-}
-
-# Checks for 32-bit boxes with more than 2GB of RAM
-my ($arch);
-
-sub check_architecture {
- if ( $doremote eq 1 ) { return; }
- if ( `uname` =~ /SunOS/ && `isainfo -b` =~ /64/ ) {
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` !~ /SunOS/ && `uname -m` =~ /64/ ) {
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` =~ /AIX/ && `bootinfo -K` =~ /64/ ) {
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` =~ /NetBSD|OpenBSD/ && `sysctl -b hw.machine` =~ /64/ ) {
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` =~ /FreeBSD/ && `sysctl -b hw.machine_arch` =~ /64/ ) {
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` =~ /Darwin/ && `uname -m` =~ /Power Macintosh/ ) {
-
-# Darwin box.local 9.8.0 Darwin Kernel Version 9.8.0: Wed Jul 15 16:57:01 PDT 2009; root:xnu1228.15.4~1/RELEASE_PPC Power Macintosh
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- elsif ( `uname` =~ /Darwin/ && `uname -m` =~ /x86_64/ ) {
-
-# Darwin gibas.local 12.3.0 Darwin Kernel Version 12.3.0: Sun Jan 6 22:37:10 PST 2013; root:xnu-2050.22.13~1/RELEASE_X86_64 x86_64
- $arch = 64;
- goodprint "Operating on 64-bit architecture";
- }
- else {
- $arch = 32;
- if ( $physical_memory > 2147483648 ) {
- badprint
-"Switch to 64-bit OS - MySQL cannot currently use all of your RAM";
- }
- else {
- goodprint
- "Operating on 32-bit architecture with less than 2GB RAM";
- }
- }
- $result{'OS'}{'Architecture'} = "$arch bits";
-}
-
-# Start up a ton of storage engine counts/statistics
-my ( %enginestats, %enginecount, $fragtables );
-
-sub check_storage_engines {
- if ( $opt{skipsize} eq 1 ) {
- prettyprint
-"\n-------- Storage Engine Statistics -------------------------------------------";
- infoprint "Skipped due to --skipsize option";
- return;
- }
- prettyprint
-"\n-------- Storage Engine Statistics -------------------------------------------";
-
- my $engines;
- if ( mysql_version_ge( 5, 1, 5 ) ) {
- my @engineresults = select_array
-"SELECT ENGINE,SUPPORT FROM information_schema.ENGINES WHERE ENGINE NOT IN ('performance_schema','MyISAM','MERGE','MEMORY') ORDER BY ENGINE ASC";
- foreach my $line (@engineresults) {
- my ( $engine, $engineenabled );
- ( $engine, $engineenabled ) = $line =~ /([a-zA-Z_]*)\s+([a-zA-Z]+)/;
- $result{'Engine'}{$engine}{'Enabled'} = $engineenabled;
- $engines .=
- ( $engineenabled eq "YES" || $engineenabled eq "DEFAULT" )
- ? greenwrap "+" . $engine . " "
- : redwrap "-" . $engine . " ";
- }
- }
- else {
- $engines .=
- ( defined $myvar{'have_archive'} && $myvar{'have_archive'} eq "YES" )
- ? greenwrap "+Archive "
- : redwrap "-Archive ";
- $engines .=
- ( defined $myvar{'have_bdb'} && $myvar{'have_bdb'} eq "YES" )
- ? greenwrap "+BDB "
- : redwrap "-BDB ";
- $engines .=
- ( defined $myvar{'have_federated_engine'}
- && $myvar{'have_federated_engine'} eq "YES" )
- ? greenwrap "+Federated "
- : redwrap "-Federated ";
- $engines .=
- ( defined $myvar{'have_innodb'} && $myvar{'have_innodb'} eq "YES" )
- ? greenwrap "+InnoDB "
- : redwrap "-InnoDB ";
- $engines .=
- ( defined $myvar{'have_isam'} && $myvar{'have_isam'} eq "YES" )
- ? greenwrap "+ISAM "
- : redwrap "-ISAM ";
- $engines .=
- ( defined $myvar{'have_aria'} && $myvar{'have_aria'} eq "YES" )
- ? greenwrap "+Aria "
- : redwrap "-Aria ";
- $engines .=
- ( defined $myvar{'have_ndbcluster'}
- && $myvar{'have_ndbcluster'} eq "YES" )
- ? greenwrap "+NDBCluster "
- : redwrap "-NDBCluster ";
- }
-
- my @dblist = grep {$_ ne 'lost+found' } select_array "SHOW DATABASES";
-
- $result{'Databases'}{'List'} = [@dblist];
- infoprint "Status: $engines";
- if ( mysql_version_ge( 5, 1, 5 ) ) {
-
-# MySQL 5 servers can have table sizes calculated quickly from information schema
- my @templist = select_array
-"SELECT ENGINE,SUM(DATA_LENGTH+INDEX_LENGTH),COUNT(ENGINE),SUM(DATA_LENGTH),SUM(INDEX_LENGTH) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema', 'performance_schema', 'mysql') AND ENGINE IS NOT NULL GROUP BY ENGINE ORDER BY ENGINE ASC;";
-
- my ( $engine, $size, $count, $dsize, $isize );
- foreach my $line (@templist) {
- ( $engine, $size, $count, $dsize, $isize ) =
- $line =~ /([a-zA-Z_]*)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/;
- if ( !defined($size) ) { next; }
- $enginestats{$engine} = $size;
- $enginecount{$engine} = $count;
- $result{'Engine'}{$engine}{'Table Number'} = $count;
- $result{'Engine'}{$engine}{'Total Size'} = $size;
- $result{'Engine'}{$engine}{'Data Size'} = $dsize;
- $result{'Engine'}{$engine}{'Index Size'} = $isize;
- }
- $fragtables = select_one
-"SELECT COUNT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema', 'mysql') AND Data_free > 0 AND NOT ENGINE='MEMORY'";
- chomp($fragtables);
- $result{'Tables'}{'Fragmented tables'} =
- [ select_array
-"SELECT CONCAT(CONCAT(TABLE_SCHEMA, '.'), TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema','performance_schema', 'mysql') AND Data_free > 0 AND NOT ENGINE='MEMORY'"
- ];
-
- }
- else {
-
- # MySQL < 5 servers take a lot of work to get table sizes
- my @tblist;
-
- # Now we build a database list, and loop through it to get storage engine stats for tables
- foreach my $db (@dblist) {
- chomp($db);
- if ( $db eq "information_schema"
- or $db eq "performance_schema"
- or $db eq "mysql"
- or $db eq "lost+found" )
- {
- next;
- }
- my @ixs = ( 1, 6, 9 );
- if ( !mysql_version_ge( 4, 1 ) ) {
-
- # MySQL 3.23/4.0 keeps Data_Length in the 5th (0-based) column
- @ixs = ( 1, 5, 8 );
- }
- push( @tblist,
- map { [ (split)[@ixs] ] }
- select_array "SHOW TABLE STATUS FROM \\\`$db\\\`" );
- }
-
- # Parse through the table list to generate storage engine counts/statistics
- $fragtables = 0;
- foreach my $tbl (@tblist) {
- debugprint "Data dump ". Dumper (@$tbl);
- my ( $engine, $size, $datafree ) = @$tbl;
- next if $engine eq 'NULL';
- $size=0 if $size eq 'NULL';
- $datafree=0 if $datafree eq 'NULL';
- if ( defined $enginestats{$engine} ) {
- $enginestats{$engine} += $size;
- $enginecount{$engine} += 1;
- }
- else {
- $enginestats{$engine} = $size;
- $enginecount{$engine} = 1;
- }
- if ( $datafree > 0 ) {
- $fragtables++;
- }
- }
- }
- while ( my ( $engine, $size ) = each(%enginestats) ) {
- infoprint "Data in $engine tables: "
- . hr_bytes_rnd($size)
- . " (Tables: "
- . $enginecount{$engine} . ")" . "";
- }
-
- # If the storage engine isn't being used, recommend it to be disabled
- if ( !defined $enginestats{'InnoDB'}
- && defined $myvar{'have_innodb'}
- && $myvar{'have_innodb'} eq "YES" )
- {
- badprint "InnoDB is enabled but isn't being used";
- push( @generalrec,
- "Add skip-innodb to MySQL configuration to disable InnoDB" );
- }
- if ( !defined $enginestats{'BerkeleyDB'}
- && defined $myvar{'have_bdb'}
- && $myvar{'have_bdb'} eq "YES" )
- {
- badprint "BDB is enabled but isn't being used";
- push( @generalrec,
- "Add skip-bdb to MySQL configuration to disable BDB" );
- }
- if ( !defined $enginestats{'ISAM'}
- && defined $myvar{'have_isam'}
- && $myvar{'have_isam'} eq "YES" )
- {
- badprint "MYISAM is enabled but isn't being used";
- push( @generalrec,
-"Add skip-isam to MySQL configuration to disable ISAM (MySQL > 4.1.0)"
- );
- }
-
- # Fragmented tables
- if ( $fragtables > 0 ) {
- badprint "Total fragmented tables: $fragtables";
- push( @generalrec,
- "Run OPTIMIZE TABLE to defragment tables for better performance" );
- }
- else {
- goodprint "Total fragmented tables: $fragtables";
- }
-
- # Auto increments
- my %tblist;
-
- # Find the maximum integer
- my $maxint = select_one "SELECT ~0";
- $result{'MaxInt'} = $maxint;
-
-# Now we use a database list, and loop through it to get storage engine stats for tables
- foreach my $db (@dblist) {
- chomp($db);
-
- if ( !$tblist{$db} ) {
- $tblist{$db} = ();
- }
-
- if ( $db eq "information_schema" ) { next; }
- my @ia = ( 0, 10 );
- if ( !mysql_version_ge( 4, 1 ) ) {
-
- # MySQL 3.23/4.0 keeps Data_Length in the 5th (0-based) column
- @ia = ( 0, 9 );
- }
- push(
- @{ $tblist{$db} },
- map { [ (split)[@ia] ] }
- select_array "SHOW TABLE STATUS FROM \\\`$db\\\`"
- );
- }
-
- my @dbnames = keys %tblist;
-
- foreach my $db (@dbnames) {
- foreach my $tbl ( @{ $tblist{$db} } ) {
- my ( $name, $autoincrement ) = @$tbl;
-
- if ( $autoincrement =~ /^\d+?$/ ) {
- my $percent = percentage( $autoincrement, $maxint );
- $result{'PctAutoIncrement'}{"$db.$name"} = $percent;
- if ( $percent >= 75 ) {
- badprint
-"Table '$db.$name' has an autoincrement value near max capacity ($percent%)";
- }
- }
- }
- }
-
-}
-
-my %mycalc;
-
-sub calculations {
- if ( $mystat{'Questions'} < 1 ) {
- badprint
- "Your server has not answered any queries - cannot continue...";
- exit 2;
- }
-
- # Per-thread memory
- if ( mysql_version_ge(4) ) {
- $mycalc{'per_thread_buffers'} =
- $myvar{'read_buffer_size'} +
- $myvar{'read_rnd_buffer_size'} +
- $myvar{'sort_buffer_size'} +
- $myvar{'thread_stack'} +
- $myvar{'join_buffer_size'};
- }
- else {
- $mycalc{'per_thread_buffers'} =
- $myvar{'record_buffer'} +
- $myvar{'record_rnd_buffer'} +
- $myvar{'sort_buffer'} +
- $myvar{'thread_stack'} +
- $myvar{'join_buffer_size'};
- }
- $mycalc{'total_per_thread_buffers'} =
- $mycalc{'per_thread_buffers'} * $myvar{'max_connections'};
- $mycalc{'max_total_per_thread_buffers'} =
- $mycalc{'per_thread_buffers'} * $mystat{'Max_used_connections'};
-
- # Server-wide memory
- $mycalc{'max_tmp_table_size'} =
- ( $myvar{'tmp_table_size'} > $myvar{'max_heap_table_size'} )
- ? $myvar{'max_heap_table_size'}
- : $myvar{'tmp_table_size'};
- $mycalc{'server_buffers'} =
- $myvar{'key_buffer_size'} + $mycalc{'max_tmp_table_size'};
- $mycalc{'server_buffers'} +=
- ( defined $myvar{'innodb_buffer_pool_size'} )
- ? $myvar{'innodb_buffer_pool_size'}
- : 0;
- $mycalc{'server_buffers'} +=
- ( defined $myvar{'innodb_additional_mem_pool_size'} )
- ? $myvar{'innodb_additional_mem_pool_size'}
- : 0;
- $mycalc{'server_buffers'} +=
- ( defined $myvar{'innodb_log_buffer_size'} )
- ? $myvar{'innodb_log_buffer_size'}
- : 0;
- $mycalc{'server_buffers'} +=
- ( defined $myvar{'query_cache_size'} ) ? $myvar{'query_cache_size'} : 0;
- $mycalc{'server_buffers'} +=
- ( defined $myvar{'aria_pagecache_buffer_size'} )
- ? $myvar{'aria_pagecache_buffer_size'}
- : 0;
-
-# Global memory
-# Max used memory is memory used by MySQL based on Max_used_connections
-# This is the max memory used theorically calculated with the max concurrent connection number reached by mysql
- $mycalc{'max_used_memory'} =
- $mycalc{'server_buffers'} + $mycalc{"max_total_per_thread_buffers"};
- $mycalc{'pct_max_used_memory'} =
- percentage( $mycalc{'max_used_memory'}, $physical_memory );
-
-# Total possible memory is memory needed by MySQL based on max_connections
-# This is the max memory MySQL can theorically used if all connections allowed has opened by mysql
- $mycalc{'max_peak_memory'} =
- $mycalc{'server_buffers'} + $mycalc{'total_per_thread_buffers'};
- $mycalc{'pct_max_physical_memory'} =
- percentage( $mycalc{'max_peak_memory'}, $physical_memory );
-
- debugprint "Max Used Memory: "
- . hr_bytes( $mycalc{'max_used_memory'} ) . "";
- debugprint "Max Used Percentage RAM: "
- . $mycalc{'pct_max_used_memory'} . "%";
-
- debugprint "Max Peak Memory: "
- . hr_bytes( $mycalc{'max_peak_memory'} ) . "";
- debugprint "Max Peak Percentage RAM: "
- . $mycalc{'pct_max_physical_memory'} . "%";
-
- # Slow queries
- $mycalc{'pct_slow_queries'} =
- int( ( $mystat{'Slow_queries'} / $mystat{'Questions'} ) * 100 );
-
- # Connections
- $mycalc{'pct_connections_used'} = int(
- ( $mystat{'Max_used_connections'} / $myvar{'max_connections'} ) * 100 );
- $mycalc{'pct_connections_used'} =
- ( $mycalc{'pct_connections_used'} > 100 )
- ? 100
- : $mycalc{'pct_connections_used'};
-
- # Aborted Connections
- $mycalc{'pct_connections_aborted'} =
- percentage( $mystat{'Aborted_connects'}, $mystat{'Connections'} );
- debugprint "Aborted_connects: " . $mystat{'Aborted_connects'} . "";
- debugprint "Connections: " . $mystat{'Connections'} . "";
- debugprint "pct_connections_aborted: "
- . $mycalc{'pct_connections_aborted'} . "";
-
- # Key buffers
- if ( mysql_version_ge( 4, 1 ) && $myvar{'key_buffer_size'} > 0 ) {
- $mycalc{'pct_key_buffer_used'} = sprintf(
- "%.1f",
- (
- 1 - (
- (
- $mystat{'Key_blocks_unused'} *
- $myvar{'key_cache_block_size'}
- ) / $myvar{'key_buffer_size'}
- )
- ) * 100
- );
- }
- else {
- $mycalc{'pct_key_buffer_used'} = 0;
- }
-
- if ( $mystat{'Key_read_requests'} > 0 ) {
- $mycalc{'pct_keys_from_mem'} = sprintf(
- "%.1f",
- (
- 100 - (
- ( $mystat{'Key_reads'} / $mystat{'Key_read_requests'} ) *
- 100
- )
- )
- );
- }
- else {
- $mycalc{'pct_keys_from_mem'} = 0;
- }
- if ( defined $mystat{'Aria_pagecache_read_requests'}
- && $mystat{'Aria_pagecache_read_requests'} > 0 )
- {
- $mycalc{'pct_aria_keys_from_mem'} = sprintf(
- "%.1f",
- (
- 100 - (
- (
- $mystat{'Aria_pagecache_reads'} /
- $mystat{'Aria_pagecache_read_requests'}
- ) * 100
- )
- )
- );
- }
- else {
- $mycalc{'pct_aria_keys_from_mem'} = 0;
- }
-
- if ( $mystat{'Key_write_requests'} > 0 ) {
- $mycalc{'pct_wkeys_from_mem'} = sprintf(
- "%.1f",
- (
- 100 - (
- ( $mystat{'Key_writes'} / $mystat{'Key_write_requests'} ) *
- 100
- )
- )
- );
- }
- else {
- $mycalc{'pct_wkeys_from_mem'} = 0;
- }
-
- if ( $doremote eq 0 and !mysql_version_ge(5) ) {
- my $size = 0;
- $size += (split)[0]
- for
-`find $myvar{'datadir'} -name "*.MYI" 2>&1 | xargs du -L $duflags 2>&1`;
- $mycalc{'total_myisam_indexes'} = $size;
- $mycalc{'total_aria_indexes'} = 0;
- }
- elsif ( mysql_version_ge(5) ) {
- $mycalc{'total_myisam_indexes'} = select_one
-"SELECT IFNULL(SUM(INDEX_LENGTH),0) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema') AND ENGINE = 'MyISAM';";
- $mycalc{'total_aria_indexe'} = select_one
-"SELECT IFNULL(SUM(INDEX_LENGTH),0) FROM information_schema.TABLES WHERE TABLE_SCHEMA NOT IN ('information_schema') AND ENGINE = 'Aria';";
- }
- if ( defined $mycalc{'total_myisam_indexes'}
- and $mycalc{'total_myisam_indexes'} == 0 )
- {
- $mycalc{'total_myisam_indexes'} = "fail";
- }
- elsif ( defined $mycalc{'total_myisam_indexes'} ) {
- chomp( $mycalc{'total_myisam_indexes'} );
- }
- if ( defined $mycalc{'total_aria_indexes'}
- and $mycalc{'total_aria_indexes'} == 0 )
- {
- $mycalc{'total_aria_indexes'} = "fail";
- }
- elsif ( defined $mycalc{'total_aria_indexes'} ) {
- chomp( $mycalc{'total_aria_indexes'} );
- }
-
- # Query cache
- if ( mysql_version_ge(4) ) {
- $mycalc{'query_cache_efficiency'} = sprintf(
- "%.1f",
- (
- $mystat{'Qcache_hits'} /
- ( $mystat{'Com_select'} + $mystat{'Qcache_hits'} )
- ) * 100
- );
- if ( $myvar{'query_cache_size'} ) {
- $mycalc{'pct_query_cache_used'} = sprintf(
- "%.1f",
- 100 - (
- $mystat{'Qcache_free_memory'} / $myvar{'query_cache_size'}
- ) * 100
- );
- }
- if ( $mystat{'Qcache_lowmem_prunes'} == 0 ) {
- $mycalc{'query_cache_prunes_per_day'} = 0;
- }
- else {
- $mycalc{'query_cache_prunes_per_day'} = int(
- $mystat{'Qcache_lowmem_prunes'} / ( $mystat{'Uptime'} / 86400 )
- );
- }
- }
-
- # Sorting
- $mycalc{'total_sorts'} = $mystat{'Sort_scan'} + $mystat{'Sort_range'};
- if ( $mycalc{'total_sorts'} > 0 ) {
- $mycalc{'pct_temp_sort_table'} = int(
- ( $mystat{'Sort_merge_passes'} / $mycalc{'total_sorts'} ) * 100 );
- }
-
- # Joins
- $mycalc{'joins_without_indexes'} =
- $mystat{'Select_range_check'} + $mystat{'Select_full_join'};
- $mycalc{'joins_without_indexes_per_day'} =
- int( $mycalc{'joins_without_indexes'} / ( $mystat{'Uptime'} / 86400 ) );
-
- # Temporary tables
- if ( $mystat{'Created_tmp_tables'} > 0 ) {
- if ( $mystat{'Created_tmp_disk_tables'} > 0 ) {
- $mycalc{'pct_temp_disk'} = int(
- (
- $mystat{'Created_tmp_disk_tables'} /
- $mystat{'Created_tmp_tables'}
- ) * 100
- );
- }
- else {
- $mycalc{'pct_temp_disk'} = 0;
- }
- }
-
- # Table cache
- if ( $mystat{'Opened_tables'} > 0 ) {
- $mycalc{'table_cache_hit_rate'} =
- int( $mystat{'Open_tables'} * 100 / $mystat{'Opened_tables'} );
- }
- else {
- $mycalc{'table_cache_hit_rate'} = 100;
- }
-
- # Open files
- if ( $myvar{'open_files_limit'} > 0 ) {
- $mycalc{'pct_files_open'} =
- int( $mystat{'Open_files'} * 100 / $myvar{'open_files_limit'} );
- }
-
- # Table locks
- if ( $mystat{'Table_locks_immediate'} > 0 ) {
- if ( $mystat{'Table_locks_waited'} == 0 ) {
- $mycalc{'pct_table_locks_immediate'} = 100;
- }
- else {
- $mycalc{'pct_table_locks_immediate'} = int(
- $mystat{'Table_locks_immediate'} * 100 / (
- $mystat{'Table_locks_waited'} +
- $mystat{'Table_locks_immediate'}
- )
- );
- }
- }
-
- # Thread cache
- $mycalc{'thread_cache_hit_rate'} =
- int( 100 -
- ( ( $mystat{'Threads_created'} / $mystat{'Connections'} ) * 100 ) );
-
- # Other
- if ( $mystat{'Connections'} > 0 ) {
- $mycalc{'pct_aborted_connections'} =
- int( ( $mystat{'Aborted_connects'} / $mystat{'Connections'} ) * 100 );
- }
- if ( $mystat{'Questions'} > 0 ) {
- $mycalc{'total_reads'} = $mystat{'Com_select'};
- $mycalc{'total_writes'} =
- $mystat{'Com_delete'} +
- $mystat{'Com_insert'} +
- $mystat{'Com_update'} +
- $mystat{'Com_replace'};
- if ( $mycalc{'total_reads'} == 0 ) {
- $mycalc{'pct_reads'} = 0;
- $mycalc{'pct_writes'} = 100;
- }
- else {
- $mycalc{'pct_reads'} = int(
- (
- $mycalc{'total_reads'} /
- ( $mycalc{'total_reads'} + $mycalc{'total_writes'} )
- ) * 100
- );
- $mycalc{'pct_writes'} = 100 - $mycalc{'pct_reads'};
- }
- }
-
- # InnoDB
- if ( $myvar{'have_innodb'} eq "YES" ) {
- $mycalc{'innodb_log_size_pct'} =
- ( $myvar{'innodb_log_file_size'} * 100 /
- $myvar{'innodb_buffer_pool_size'} );
- }
- (
- $mystat{'Innodb_buffer_pool_read_requests'},
- $mystat{'Innodb_buffer_pool_reads'}
- )
- = ( 1, 1 )
- unless defined $mystat{'Innodb_buffer_pool_reads'};
- $mycalc{'pct_read_efficiency'} = percentage(
- (
- $mystat{'Innodb_buffer_pool_read_requests'} -
- $mystat{'Innodb_buffer_pool_reads'}
- ),
- $mystat{'Innodb_buffer_pool_read_requests'}
- ) if defined $mystat{'Innodb_buffer_pool_read_requests'};
- debugprint "pct_read_efficiency: " . $mycalc{'pct_read_efficiency'} . "";
- debugprint "Innodb_buffer_pool_reads: "
- . $mystat{'Innodb_buffer_pool_reads'} . "";
- debugprint "Innodb_buffer_pool_read_requests: "
- . $mystat{'Innodb_buffer_pool_read_requests'} . "";
- (
- $mystat{'Innodb_buffer_pool_write_requests'},
- $mystat{'Innodb_buffer_pool_writes'}
- )
- = ( 1, 1 )
- unless defined $mystat{'Innodb_buffer_pool_writes'};
- $mycalc{'pct_write_efficiency'} = percentage(
- (
- $mystat{'Innodb_buffer_pool_write_requests'} -
- $mystat{'Innodb_buffer_pool_writes'}
- ),
- $mystat{'Innodb_buffer_pool_write_requests'}
- ) if defined $mystat{'Innodb_buffer_pool_write_requests'};
- debugprint "pct_write_efficiency: " . $mycalc{'pct_read_efficiency'} . "";
- debugprint "Innodb_buffer_pool_writes: "
- . $mystat{'Innodb_buffer_pool_writes'} . "";
- debugprint "Innodb_buffer_pool_write_requests: "
- . $mystat{'Innodb_buffer_pool_write_requests'} . "";
- $mycalc{'pct_innodb_buffer_used'} = percentage(
- (
- $mystat{'Innodb_buffer_pool_pages_total'} -
- $mystat{'Innodb_buffer_pool_pages_free'}
- ),
- $mystat{'Innodb_buffer_pool_pages_total'}
- ) if defined $mystat{'Innodb_buffer_pool_pages_total'};
-
- # Binlog Cache
- if ( $myvar{'log_bin'} ne 'OFF' ) {
- $mycalc{'pct_binlog_cache'} = percentage(
- $mystat{'Binlog_cache_use'} - $mystat{'Binlog_cache_disk_use'},
- $mystat{'Binlog_cache_use'} );
- }
-}
-
-sub mysql_stats {
- prettyprint
-"\n-------- Performance Metrics -------------------------------------------------";
-
- # Show uptime, queries per second, connections, traffic stats
- my $qps;
- if ( $mystat{'Uptime'} > 0 ) {
- $qps = sprintf( "%.3f", $mystat{'Questions'} / $mystat{'Uptime'} );
- }
- push( @generalrec,
- "MySQL started within last 24 hours - recommendations may be inaccurate"
- ) if ( $mystat{'Uptime'} < 86400 );
- infoprint "Up for: "
- . pretty_uptime( $mystat{'Uptime'} ) . " ("
- . hr_num( $mystat{'Questions'} ) . " q ["
- . hr_num($qps)
- . " qps], "
- . hr_num( $mystat{'Connections'} )
- . " conn," . " TX: "
- . hr_num( $mystat{'Bytes_sent'} )
- . ", RX: "
- . hr_num( $mystat{'Bytes_received'} ) . ")";
- infoprint "Reads / Writes: "
- . $mycalc{'pct_reads'} . "% / "
- . $mycalc{'pct_writes'} . "%";
-
- # Binlog Cache
- if ( $myvar{'log_bin'} eq 'OFF' ) {
- infoprint "Binary logging is disabled";
- }
- else {
- infoprint "Binary logging is enabled (GTID MODE: "
- . ( defined( $myvar{'gtid_mode'} ) ? $myvar{'gtid_mode'} : "OFF" )
- . ")";
- }
-
- # Memory usage
- infoprint "Total buffers: "
- . hr_bytes( $mycalc{'server_buffers'} )
- . " global + "
- . hr_bytes( $mycalc{'per_thread_buffers'} )
- . " per thread ($myvar{'max_connections'} max threads)";
-
- if ( $opt{buffers} ne 0 ) {
- infoprint "Global Buffers";
- infoprint " +-- Key Buffer: "
- . hr_bytes( $myvar{'key_buffer_size'} ) . "";
- infoprint " +-- Max Tmp Table: "
- . hr_bytes( $mycalc{'max_tmp_table_size'} ) . "";
-
- if ( defined $myvar{'query_cache_type'} ) {
- infoprint "Query Cache Buffers";
- infoprint " +-- Query Cache: "
- . $myvar{'query_cache_type'} . " - "
- . (
- $myvar{'query_cache_type'} eq 0 |
- $myvar{'query_cache_type'} eq 'OFF' ? "DISABLED"
- : ( $myvar{'query_cache_type'} eq 1 ? "ALL REQUESTS"
- : "ON DEMAND" )
- ) . "";
- infoprint " +-- Query Cache Size: "
- . hr_bytes( $myvar{'query_cache_size'} ) . "";
- }
-
- infoprint "Per Thread Buffers";
- infoprint " +-- Read Buffer: "
- . hr_bytes( $myvar{'read_buffer_size'} ) . "";
- infoprint " +-- Read RND Buffer: "
- . hr_bytes( $myvar{'read_rnd_buffer_size'} ) . "";
- infoprint " +-- Sort Buffer: "
- . hr_bytes( $myvar{'sort_buffer_size'} ) . "";
- infoprint " +-- Thread stack: "
- . hr_bytes( $myvar{'thread_stack'} ) . "";
- infoprint " +-- Join Buffer: "
- . hr_bytes( $myvar{'join_buffer_size'} ) . "";
- if ( $myvar{'log_bin'} ne 'OFF' ) {
- infoprint "Binlog Cache Buffers";
- infoprint " +-- Binlog Cache: "
- . hr_bytes( $myvar{'binlog_cache_size'} ) . "";
- }
- }
-
- if ( $arch
- && $arch == 32
- && $mycalc{'max_used_memory'} > 2 * 1024 * 1024 * 1024 )
- {
- badprint
-"Allocating > 2GB RAM on 32-bit systems can cause system instability";
- badprint "Maximum reached memory usage: "
- . hr_bytes( $mycalc{'max_used_memory'} )
- . " ($mycalc{'pct_max_used_memory'}% of installed RAM)";
- }
- elsif ( $mycalc{'pct_max_used_memory'} > 85 ) {
- badprint "Maximum reached memory usage: "
- . hr_bytes( $mycalc{'max_used_memory'} )
- . " ($mycalc{'pct_max_used_memory'}% of installed RAM)";
- }
- else {
- goodprint "Maximum reached memory usage: "
- . hr_bytes( $mycalc{'max_used_memory'} )
- . " ($mycalc{'pct_max_used_memory'}% of installed RAM)";
- }
-
- if ( $mycalc{'pct_max_physical_memory'} > 85 ) {
- badprint "Maximum possible memory usage: "
- . hr_bytes( $mycalc{'max_peak_memory'} )
- . " ($mycalc{'pct_max_physical_memory'}% of installed RAM)";
- push( @generalrec,
- "Reduce your overall MySQL memory footprint for system stability" );
- }
- else {
- goodprint "Maximum possible memory usage: "
- . hr_bytes( $mycalc{'max_peak_memory'} )
- . " ($mycalc{'pct_max_physical_memory'}% of installed RAM)";
- }
-
- # Slow queries
- if ( $mycalc{'pct_slow_queries'} > 5 ) {
- badprint "Slow queries: $mycalc{'pct_slow_queries'}% ("
- . hr_num( $mystat{'Slow_queries'} ) . "/"
- . hr_num( $mystat{'Questions'} ) . ")";
- }
- else {
- goodprint "Slow queries: $mycalc{'pct_slow_queries'}% ("
- . hr_num( $mystat{'Slow_queries'} ) . "/"
- . hr_num( $mystat{'Questions'} ) . ")";
- }
- if ( $myvar{'long_query_time'} > 10 ) {
- push( @adjvars, "long_query_time (<= 10)" );
- }
- if ( defined( $myvar{'log_slow_queries'} ) ) {
- if ( $myvar{'log_slow_queries'} eq "OFF" ) {
- push( @generalrec,
- "Enable the slow query log to troubleshoot bad queries" );
- }
- }
-
- # Connections
- if ( $mycalc{'pct_connections_used'} > 85 ) {
- badprint
-"Highest connection usage: $mycalc{'pct_connections_used'}% ($mystat{'Max_used_connections'}/$myvar{'max_connections'})";
- push( @adjvars,
- "max_connections (> " . $myvar{'max_connections'} . ")" );
- push( @adjvars,
- "wait_timeout (< " . $myvar{'wait_timeout'} . ")",
- "interactive_timeout (< " . $myvar{'interactive_timeout'} . ")" );
- push( @generalrec,
-"Reduce or eliminate persistent connections to reduce connection usage"
- );
- }
- else {
- goodprint
-"Highest usage of available connections: $mycalc{'pct_connections_used'}% ($mystat{'Max_used_connections'}/$myvar{'max_connections'})";
- }
-
- # Aborted Connections
- if ( $mycalc{'pct_connections_aborted'} > 3 ) {
- badprint
-"Aborted connections: $mycalc{'pct_connections_aborted'}% ($mystat{'Aborted_connects'}/$mystat{'Connections'})";
- push( @generalrec,
- "Reduce or eliminate unclosed connections and network issues" );
- }
- else {
- goodprint
-"Aborted connections: $mycalc{'pct_connections_aborted'}% ($mystat{'Aborted_connects'}/$mystat{'Connections'})";
- }
-
- # Query cache
- if ( !mysql_version_ge(4) ) {
-
- # MySQL versions < 4.01 don't support query caching
- push( @generalrec,
- "Upgrade MySQL to version 4+ to utilize query caching" );
- }
- elsif ( $myvar{'query_cache_size'} < 1 ) {
- badprint "Query cache is disabled";
- push( @adjvars, "query_cache_size (>= 8M)" );
- }
- elsif ( $myvar{'query_cache_type'} eq "OFF" ) {
- badprint "Query cache is disabled";
- push( @adjvars, "query_cache_type (=1)" );
- }
- elsif ( $mystat{'Com_select'} == 0 ) {
- badprint
- "Query cache cannot be analyzed - no SELECT statements executed";
- }
- else {
- if ( $mycalc{'query_cache_efficiency'} < 20 ) {
- badprint
- "Query cache efficiency: $mycalc{'query_cache_efficiency'}% ("
- . hr_num( $mystat{'Qcache_hits'} )
- . " cached / "
- . hr_num( $mystat{'Qcache_hits'} + $mystat{'Com_select'} )
- . " selects)";
- push( @adjvars,
- "query_cache_limit (> "
- . hr_bytes_rnd( $myvar{'query_cache_limit'} )
- . ", or use smaller result sets)" );
- }
- else {
- goodprint
- "Query cache efficiency: $mycalc{'query_cache_efficiency'}% ("
- . hr_num( $mystat{'Qcache_hits'} )
- . " cached / "
- . hr_num( $mystat{'Qcache_hits'} + $mystat{'Com_select'} )
- . " selects)";
- }
- if ( $mycalc{'query_cache_prunes_per_day'} > 98 ) {
- badprint
-"Query cache prunes per day: $mycalc{'query_cache_prunes_per_day'}";
- if ( $myvar{'query_cache_size'} >= 128 * 1024 * 1024 ) {
- push( @generalrec,
-"Increasing the query_cache size over 128M may reduce performance"
- );
- push( @adjvars,
- "query_cache_size (> "
- . hr_bytes_rnd( $myvar{'query_cache_size'} )
- . ") [see warning above]" );
- }
- else {
- push( @adjvars,
- "query_cache_size (> "
- . hr_bytes_rnd( $myvar{'query_cache_size'} )
- . ")" );
- }
- }
- else {
- goodprint
-"Query cache prunes per day: $mycalc{'query_cache_prunes_per_day'}";
- }
- }
-
- # Sorting
- if ( $mycalc{'total_sorts'} == 0 ) {
-
- # For the sake of space, we will be quiet here
- # No sorts have run yet
- }
- elsif ( $mycalc{'pct_temp_sort_table'} > 10 ) {
- badprint
- "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% ("
- . hr_num( $mystat{'Sort_merge_passes'} )
- . " temp sorts / "
- . hr_num( $mycalc{'total_sorts'} )
- . " sorts)";
- push( @adjvars,
- "sort_buffer_size (> "
- . hr_bytes_rnd( $myvar{'sort_buffer_size'} )
- . ")" );
- push( @adjvars,
- "read_rnd_buffer_size (> "
- . hr_bytes_rnd( $myvar{'read_rnd_buffer_size'} )
- . ")" );
- }
- else {
- goodprint
- "Sorts requiring temporary tables: $mycalc{'pct_temp_sort_table'}% ("
- . hr_num( $mystat{'Sort_merge_passes'} )
- . " temp sorts / "
- . hr_num( $mycalc{'total_sorts'} )
- . " sorts)";
- }
-
- # Joins
- if ( $mycalc{'joins_without_indexes_per_day'} > 250 ) {
- badprint
- "Joins performed without indexes: $mycalc{'joins_without_indexes'}";
- push( @adjvars,
- "join_buffer_size (> "
- . hr_bytes( $myvar{'join_buffer_size'} )
- . ", or always use indexes with joins)" );
- push( @generalrec,
- "Adjust your join queries to always utilize indexes" );
- }
- else {
-
- # For the sake of space, we will be quiet here
- # No joins have run without indexes
- }
-
- # Temporary tables
- if ( $mystat{'Created_tmp_tables'} > 0 ) {
- if ( $mycalc{'pct_temp_disk'} > 25
- && $mycalc{'max_tmp_table_size'} < 256 * 1024 * 1024 )
- {
- badprint
- "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% ("
- . hr_num( $mystat{'Created_tmp_disk_tables'} )
- . " on disk / "
- . hr_num( $mystat{'Created_tmp_tables'} )
- . " total)";
- push( @adjvars,
- "tmp_table_size (> "
- . hr_bytes_rnd( $myvar{'tmp_table_size'} )
- . ")" );
- push( @adjvars,
- "max_heap_table_size (> "
- . hr_bytes_rnd( $myvar{'max_heap_table_size'} )
- . ")" );
- push( @generalrec,
-"When making adjustments, make tmp_table_size/max_heap_table_size equal"
- );
- push( @generalrec,
- "Reduce your SELECT DISTINCT queries which have no LIMIT clause" );
- }
- elsif ($mycalc{'pct_temp_disk'} > 25
- && $mycalc{'max_tmp_table_size'} >= 256 * 1024 * 1024 )
- {
- badprint
- "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% ("
- . hr_num( $mystat{'Created_tmp_disk_tables'} )
- . " on disk / "
- . hr_num( $mystat{'Created_tmp_tables'} )
- . " total)";
- push( @generalrec,
- "Temporary table size is already large - reduce result set size"
- );
- push( @generalrec,
- "Reduce your SELECT DISTINCT queries without LIMIT clauses" );
- }
- else {
- goodprint
- "Temporary tables created on disk: $mycalc{'pct_temp_disk'}% ("
- . hr_num( $mystat{'Created_tmp_disk_tables'} )
- . " on disk / "
- . hr_num( $mystat{'Created_tmp_tables'} )
- . " total)";
- }
- }
- else {
-
- # For the sake of space, we will be quiet here
- # No temporary tables have been created
- }
-
- # Thread cache
- if ( $myvar{'thread_cache_size'} eq 0 ) {
- badprint "Thread cache is disabled";
- push( @generalrec, "Set thread_cache_size to 4 as a starting value" );
- push( @adjvars, "thread_cache_size (start at 4)" );
- }
- else {
- if ( $mycalc{'thread_cache_hit_rate'} <= 50 ) {
- badprint
- "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% ("
- . hr_num( $mystat{'Threads_created'} )
- . " created / "
- . hr_num( $mystat{'Connections'} )
- . " connections)";
- push( @adjvars,
- "thread_cache_size (> $myvar{'thread_cache_size'})" );
- }
- else {
- goodprint
- "Thread cache hit rate: $mycalc{'thread_cache_hit_rate'}% ("
- . hr_num( $mystat{'Threads_created'} )
- . " created / "
- . hr_num( $mystat{'Connections'} )
- . " connections)";
- }
- }
-
- # Table cache
- my $table_cache_var = "";
- if ( $mystat{'Open_tables'} > 0 ) {
- if ( $mycalc{'table_cache_hit_rate'} < 20 ) {
- badprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% ("
- . hr_num( $mystat{'Open_tables'} )
- . " open / "
- . hr_num( $mystat{'Opened_tables'} )
- . " opened)";
- if ( mysql_version_ge( 5, 1 ) ) {
- $table_cache_var = "table_open_cache";
- }
- else {
- $table_cache_var = "table_cache";
- }
-
- push( @adjvars,
- $table_cache_var . " (> " . $myvar{$table_cache_var} . ")" );
- push( @generalrec,
- "Increase "
- . $table_cache_var
- . " gradually to avoid file descriptor limits" );
- push( @generalrec,
- "Read this before increasing "
- . $table_cache_var
- . " over 64: http://bit.ly/1mi7c4C" );
- push( @generalrec,
- "Beware that open_files_limit ("
- . $myvar{'open_files_limit'}
- . ") variable " );
- push( @generalrec,
- "should be greater than $table_cache_var ( "
- . $myvar{$table_cache_var}
- . ")" );
- }
- else {
- goodprint "Table cache hit rate: $mycalc{'table_cache_hit_rate'}% ("
- . hr_num( $mystat{'Open_tables'} )
- . " open / "
- . hr_num( $mystat{'Opened_tables'} )
- . " opened)";
- }
- }
-
- # Open files
- if ( defined $mycalc{'pct_files_open'} ) {
- if ( $mycalc{'pct_files_open'} > 85 ) {
- badprint "Open file limit used: $mycalc{'pct_files_open'}% ("
- . hr_num( $mystat{'Open_files'} ) . "/"
- . hr_num( $myvar{'open_files_limit'} ) . ")";
- push( @adjvars,
- "open_files_limit (> " . $myvar{'open_files_limit'} . ")" );
- }
- else {
- goodprint "Open file limit used: $mycalc{'pct_files_open'}% ("
- . hr_num( $mystat{'Open_files'} ) . "/"
- . hr_num( $myvar{'open_files_limit'} ) . ")";
- }
- }
-
- # Table locks
- if ( defined $mycalc{'pct_table_locks_immediate'} ) {
- if ( $mycalc{'pct_table_locks_immediate'} < 95 ) {
- badprint
-"Table locks acquired immediately: $mycalc{'pct_table_locks_immediate'}%";
- push( @generalrec,
- "Optimize queries and/or use InnoDB to reduce lock wait" );
- }
- else {
- goodprint
-"Table locks acquired immediately: $mycalc{'pct_table_locks_immediate'}% ("
- . hr_num( $mystat{'Table_locks_immediate'} )
- . " immediate / "
- . hr_num( $mystat{'Table_locks_waited'} +
- $mystat{'Table_locks_immediate'} )
- . " locks)";
- }
- }
-
- # Binlog cache
- if ( defined $mycalc{'pct_binlog_cache'} ) {
- if ( $mycalc{'pct_binlog_cache'} < 90
- && $mystat{'Binlog_cache_use'} > 0 )
- {
- badprint "Binlog cache memory access: "
- . $mycalc{'pct_binlog_cache'} . "% ( "
- . (
- $mystat{'Binlog_cache_use'} - $mystat{'Binlog_cache_disk_use'} )
- . " Memory / "
- . $mystat{'Binlog_cache_use'}
- . " Total)";
- push( @generalrec,
- "Increase binlog_cache_size (Actual value: "
- . $myvar{'binlog_cache_size'}
- . ") " );
- push( @adjvars,
- "binlog_cache_size ("
- . hr_bytes( $myvar{'binlog_cache_size'} + 16 * 1024 * 1024 )
- . " ) " );
- }
- else {
- goodprint "Binlog cache memory access: "
- . $mycalc{'pct_binlog_cache'} . "% ( "
- . (
- $mystat{'Binlog_cache_use'} - $mystat{'Binlog_cache_disk_use'} )
- . " Memory / "
- . $mystat{'Binlog_cache_use'}
- . " Total)";
- debugprint "Not enought data to validate binlog cache size\n"
- if $mystat{'Binlog_cache_use'} < 10;
- }
- }
-
- # Performance options
- if ( !mysql_version_ge( 5, 1 ) ) {
- push( @generalrec, "Upgrade to MySQL 5.5+ to use asynchrone write" );
- }
- elsif ( $myvar{'concurrent_insert'} eq "OFF" ) {
- push( @generalrec, "Enable concurrent_insert by setting it to 'ON'" );
- }
- elsif ( $myvar{'concurrent_insert'} eq 0 ) {
- push( @generalrec, "Enable concurrent_insert by setting it to 1" );
- }
-}
-
-# Recommandations for MyISAM
-sub mysql_myisam {
- prettyprint
-"\n-------- MyISAM Metrics -----------------------------------------------------";
-
- # AriaDB
-
- # Key buffer usage
- if ( defined( $mycalc{'pct_key_buffer_used'} ) ) {
- if ( $mycalc{'pct_key_buffer_used'} < 90 ) {
- badprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
- . hr_num( $myvar{'key_buffer_size'} *
- $mycalc{'pct_key_buffer_used'} /
- 100 )
- . " used / "
- . hr_num( $myvar{'key_buffer_size'} )
- . " cache)";
-
-#push(@adjvars,"key_buffer_size (\~ ".hr_num( $myvar{'key_buffer_size'} * $mycalc{'pct_key_buffer_used'} / 100).")");
- }
- else {
- goodprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
- . hr_num( $myvar{'key_buffer_size'} *
- $mycalc{'pct_key_buffer_used'} /
- 100 )
- . " used / "
- . hr_num( $myvar{'key_buffer_size'} )
- . " cache)";
- }
- }
- else {
-
- # No queries have run that would use keys
- debugprint "Key buffer used: $mycalc{'pct_key_buffer_used'}% ("
- . hr_num(
- $myvar{'key_buffer_size'} * $mycalc{'pct_key_buffer_used'} / 100 )
- . " used / "
- . hr_num( $myvar{'key_buffer_size'} )
- . " cache)";
- }
-
- # Key buffer
- if ( !defined( $mycalc{'total_myisam_indexes'} ) and $doremote == 1 ) {
- push( @generalrec,
- "Unable to calculate MyISAM indexes on remote MySQL server < 5.0.0"
- );
- }
- elsif ( $mycalc{'total_myisam_indexes'} =~ /^fail$/ ) {
- badprint
- "Cannot calculate MyISAM index size - re-run script as root user";
- }
- elsif ( $mycalc{'total_myisam_indexes'} == "0" ) {
- badprint
- "None of your MyISAM tables are indexed - add indexes immediately";
- }
- else {
- if ( $myvar{'key_buffer_size'} < $mycalc{'total_myisam_indexes'}
- && $mycalc{'pct_keys_from_mem'} < 95 )
- {
- badprint "Key buffer size / total MyISAM indexes: "
- . hr_bytes( $myvar{'key_buffer_size'} ) . "/"
- . hr_bytes( $mycalc{'total_myisam_indexes'} ) . "";
- push( @adjvars,
- "key_buffer_size (> "
- . hr_bytes( $mycalc{'total_myisam_indexes'} )
- . ")" );
- }
- else {
- goodprint "Key buffer size / total MyISAM indexes: "
- . hr_bytes( $myvar{'key_buffer_size'} ) . "/"
- . hr_bytes( $mycalc{'total_myisam_indexes'} ) . "";
- }
- if ( $mystat{'Key_read_requests'} > 0 ) {
- if ( $mycalc{'pct_keys_from_mem'} < 95 ) {
- badprint
- "Read Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% ("
- . hr_num( $mystat{'Key_read_requests'} )
- . " cached / "
- . hr_num( $mystat{'Key_reads'} )
- . " reads)";
- }
- else {
- goodprint
- "Read Key buffer hit rate: $mycalc{'pct_keys_from_mem'}% ("
- . hr_num( $mystat{'Key_read_requests'} )
- . " cached / "
- . hr_num( $mystat{'Key_reads'} )
- . " reads)";
- }
- }
- else {
-
- # No queries have run that would use keys
- debugprint "Key buffer size / total MyISAM indexes: "
- . hr_bytes( $myvar{'key_buffer_size'} ) . "/"
- . hr_bytes( $mycalc{'total_myisam_indexes'} ) . "";
- }
- if ( $mystat{'Key_write_requests'} > 0 ) {
- if ( $mycalc{'pct_wkeys_from_mem'} < 95 ) {
- badprint
- "Write Key buffer hit rate: $mycalc{'pct_wkeys_from_mem'}% ("
- . hr_num( $mystat{'Key_write_requests'} )
- . " cached / "
- . hr_num( $mystat{'Key_writes'} )
- . " writes)";
- }
- else {
- goodprint
- "Write Key buffer hit rate: $mycalc{'pct_wkeys_from_mem'}% ("
- . hr_num( $mystat{'Key_write_requests'} )
- . " cached / "
- . hr_num( $mystat{'Key_writes'} )
- . " writes)";
- }
- }
- else {
-
- # No queries have run that would use keys
- debugprint
- "Write Key buffer hit rate: $mycalc{'pct_wkeys_from_mem'}% ("
- . hr_num( $mystat{'Key_write_requests'} )
- . " cached / "
- . hr_num( $mystat{'Key_writes'} )
- . " writes)";
- }
- }
-}
-
-# Recommandations for Ariadb
-sub mysql_ariadb {
- prettyprint
-"\n-------- AriaDB Metrics -----------------------------------------------------";
-
- # AriaDB
- unless ( defined $myvar{'have_aria'}
- && $myvar{'have_aria'} eq "YES"
- && defined $enginestats{'Aria'} )
- {
- infoprint "AriaDB is disabled.";
- return;
- }
- infoprint "AriaDB is enabled.";
-
- # Aria pagecache
- if ( !defined( $mycalc{'total_aria_indexes'} ) and $doremote == 1 ) {
- push( @generalrec,
- "Unable to calculate Aria indexes on remote MySQL server < 5.0.0" );
- }
- elsif ( $mycalc{'total_aria_indexes'} =~ /^fail$/ ) {
- badprint
- "Cannot calculate Aria index size - re-run script as root user";
- }
- elsif ( $mycalc{'total_aria_indexes'} == "0" ) {
- badprint
- "None of your Aria tables are indexed - add indexes immediately";
- }
- else {
- if (
- $myvar{'aria_pagecache_buffer_size'} < $mycalc{'total_aria_indexes'}
- && $mycalc{'pct_aria_keys_from_mem'} < 95 )
- {
- badprint "Aria pagecache size / total Aria indexes: "
- . hr_bytes( $myvar{'aria_pagecache_buffer_size'} ) . "/"
- . hr_bytes( $mycalc{'total_aria_indexes'} ) . "";
- push( @adjvars,
- "aria_pagecache_buffer_size (> "
- . hr_bytes( $mycalc{'total_aria_indexes'} )
- . ")" );
- }
- else {
- goodprint "Aria pagecache size / total Aria indexes: "
- . hr_bytes( $myvar{'aria_pagecache_buffer_size'} ) . "/"
- . hr_bytes( $mycalc{'total_aria_indexes'} ) . "";
- }
- if ( $mystat{'Aria_pagecache_read_requests'} > 0 ) {
- if ( $mycalc{'pct_aria_keys_from_mem'} < 95 ) {
- badprint
-"Aria pagecache hit rate: $mycalc{'pct_aria_keys_from_mem'}% ("
- . hr_num( $mystat{'Aria_pagecache_read_requests'} )
- . " cached / "
- . hr_num( $mystat{'Aria_pagecache_reads'} )
- . " reads)";
- }
- else {
- goodprint
-"Aria pagecache hit rate: $mycalc{'pct_aria_keys_from_mem'}% ("
- . hr_num( $mystat{'Aria_pagecache_read_requests'} )
- . " cached / "
- . hr_num( $mystat{'Aria_pagecache_reads'} )
- . " reads)";
- }
- }
- else {
-
- # No queries have run that would use keys
- }
- }
-}
-
-# Recommandations for Innodb
-sub mysql_innodb {
- prettyprint
-"\n-------- InnoDB Metrics -----------------------------------------------------";
-
- # InnoDB
- unless ( defined $myvar{'have_innodb'}
- && $myvar{'have_innodb'} eq "YES"
- && defined $enginestats{'InnoDB'} )
- {
- infoprint "InnoDB is disabled.";
- if ( mysql_version_ge( 5, 5 ) ) {
- badprint
-"InnoDB Storage engine is disabled. InnoDB is the default storage engine";
- }
- return;
- }
- infoprint "InnoDB is enabled.";
-
- if ( $opt{buffers} ne 0 ) {
- infoprint "InnoDB Buffers";
- if ( defined $myvar{'innodb_buffer_pool_size'} ) {
- infoprint " +-- InnoDB Buffer Pool: "
- . hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . "";
- }
- if ( defined $myvar{'innodb_buffer_pool_instances'} ) {
- infoprint " +-- InnoDB Buffer Pool Instances: "
- . $myvar{'innodb_buffer_pool_instances'} . "";
- }
- if ( defined $myvar{'innodb_additional_mem_pool_size'} ) {
- infoprint " +-- InnoDB Additional Mem Pool: "
- . hr_bytes( $myvar{'innodb_additional_mem_pool_size'} ) . "";
- }
- if ( defined $myvar{'innodb_log_buffer_size'} ) {
- infoprint " +-- InnoDB Log Buffer: "
- . hr_bytes( $myvar{'innodb_log_buffer_size'} ) . "";
- }
- if ( defined $mystat{'Innodb_buffer_pool_pages_free'} ) {
- infoprint " +-- InnoDB Log Buffer Free: "
- . hr_bytes( $mystat{'Innodb_buffer_pool_pages_free'} ) . "";
- }
- if ( defined $mystat{'Innodb_buffer_pool_pages_total'} ) {
- infoprint " +-- InnoDB Log Buffer Used: "
- . hr_bytes( $mystat{'Innodb_buffer_pool_pages_total'} ) . "";
- }
- }
-
- # InnoDB Buffer Pull Size
- if ( $myvar{'innodb_buffer_pool_size'} > $enginestats{'InnoDB'} ) {
- goodprint "InnoDB buffer pool / data size: "
- . hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . "/"
- . hr_bytes( $enginestats{'InnoDB'} ) . "";
- }
- else {
- badprint "InnoDB buffer pool / data size: "
- . hr_bytes( $myvar{'innodb_buffer_pool_size'} ) . "/"
- . hr_bytes( $enginestats{'InnoDB'} ) . "";
- push( @adjvars,
- "innodb_buffer_pool_size (>= "
- . hr_bytes_rnd( $enginestats{'InnoDB'} )
- . ") if possible." );
- }
-
- # InnoDB Buffer Pull Instances (MySQL 5.6.6+)
- if ( defined( $myvar{'innodb_buffer_pool_instances'} ) ) {
-
- # Bad Value if > 64
- if ( $myvar{'innodb_buffer_pool_instances'} > 64 ) {
- badprint "InnoDB buffer pool instances: "
- . $myvar{'innodb_buffer_pool_instances'} . "";
- push( @adjvars, "innodb_buffer_pool_instances (<= 64)" );
- }
-
- # InnoDB Buffer Pull Size > 1Go
- if ( $myvar{'innodb_buffer_pool_size'} > 1024 * 1024 * 1024 ) {
-
-# InnoDB Buffer Pull Size / 1Go = InnoDB Buffer Pull Instances limited to 64 max.
-
- # InnoDB Buffer Pull Size > 64Go
- my $max_innodb_buffer_pool_instances =
- int( $myvar{'innodb_buffer_pool_size'} / ( 1024 * 1024 * 1024 ) );
- $max_innodb_buffer_pool_instances = 64
- if ( $max_innodb_buffer_pool_instances > 64 );
-
- if ( $myvar{'innodb_buffer_pool_instances'} !=
- $max_innodb_buffer_pool_instances )
- {
- badprint "InnoDB buffer pool instances: "
- . $myvar{'innodb_buffer_pool_instances'} . "";
- push( @adjvars,
- "innodb_buffer_pool_instances(="
- . $max_innodb_buffer_pool_instances
- . ")" );
- }
- else {
- goodprint "InnoDB buffer pool instances: "
- . $myvar{'innodb_buffer_pool_instances'} . "";
- }
-
- # InnoDB Buffer Pull Size < 1Go
- }
- else {
- if ( $myvar{'innodb_buffer_pool_instances'} != 1 ) {
- badprint
-"InnoDB buffer pool <= 1G and innodb_buffer_pool_instances(!=1).";
- push( @adjvars, "innodb_buffer_pool_instances (=1)" );
- }
- else {
- goodprint "InnoDB buffer pool instances: "
- . $myvar{'innodb_buffer_pool_instances'} . "";
- }
- }
- }
-
- # InnoDB Used Buffer Pool
- if ( defined $mycalc{'pct_innodb_buffer_used'}
- && $mycalc{'pct_innodb_buffer_used'} < 80 )
- {
- badprint "InnoDB Used buffer: "
- . $mycalc{'pct_innodb_buffer_used'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_pages_total'} -
- $mystat{'Innodb_buffer_pool_pages_free'} )
- . " used/ "
- . $mystat{'Innodb_buffer_pool_pages_total'}
- . " total)";
- }
- else {
- goodprint "InnoDB Used buffer: "
- . $mycalc{'pct_innodb_buffer_used'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_pages_total'} -
- $mystat{'Innodb_buffer_pool_pages_free'} )
- . " used/ "
- . $mystat{'Innodb_buffer_pool_pages_total'}
- . " total)";
- }
-
- # InnoDB Read efficency
- if ( defined $mycalc{'pct_read_efficiency'}
- && $mycalc{'pct_read_efficiency'} < 90 )
- {
- badprint "InnoDB Read buffer efficiency: "
- . $mycalc{'pct_read_efficiency'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_read_requests'} -
- $mystat{'Innodb_buffer_pool_reads'} )
- . " hits/ "
- . $mystat{'Innodb_buffer_pool_read_requests'}
- . " total)";
- }
- else {
- goodprint "InnoDB Read buffer efficiency: "
- . $mycalc{'pct_read_efficiency'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_read_requests'} -
- $mystat{'Innodb_buffer_pool_reads'} )
- . " hits/ "
- . $mystat{'Innodb_buffer_pool_read_requests'}
- . " total)";
- }
-
- # InnoDB Write efficiency
- if ( defined $mycalc{'pct_write_efficiency'}
- && $mycalc{'pct_write_efficiency'} < 90 )
- {
- badprint "InnoDB Write buffer efficiency: "
- . $mycalc{'pct_write_efficiency'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_write_requests'} -
- $mystat{'Innodb_buffer_pool_writes'} )
- . " hits/ "
- . $mystat{'Innodb_buffer_pool_write_requests'}
- . " total)";
- }
- else {
- goodprint "InnoDB Write buffer efficiency: "
- . $mycalc{'pct_write_efficiency'} . "% ("
- . ( $mystat{'Innodb_buffer_pool_write_requests'} -
- $mystat{'Innodb_buffer_pool_writes'} )
- . " hits/ "
- . $mystat{'Innodb_buffer_pool_write_requests'}
- . " total)";
- }
-
- # InnoDB Log Waits
- if ( defined $mystat{'Innodb_log_waits'}
- && $mystat{'Innodb_log_waits'} > 0 )
- {
- badprint "InnoDB log waits: "
- . percentage( $mystat{'Innodb_log_waits'},
- $mystat{'Innodb_log_writes'} )
- . "% ("
- . $mystat{'Innodb_log_waits'}
- . " waits / "
- . $mystat{'Innodb_log_writes'}
- . " writes)";
- push( @adjvars,
- "innodb_log_buffer_size (>= "
- . hr_bytes_rnd( $myvar{'innodb_log_buffer_size'} )
- . ")" );
- }
- else {
- goodprint "InnoDB log waits: "
- . percentage( $mystat{'Innodb_log_waits'},
- $mystat{'Innodb_log_writes'} )
- . "% ("
- . $mystat{'Innodb_log_waits'}
- . " waits / "
- . $mystat{'Innodb_log_writes'}
- . " writes)";
- }
- $result{'Calculations'} = {%mycalc};
-}
-
-# Recommandations for MySQL Databases
-sub mysql_databases {
- return if ( $opt{dbstat} == 0 );
-
- prettyprint
-"\n-------- Database Metrics ------------------------------------------------";
- unless ( mysql_version_ge( 5, 5 ) ) {
- infoprint
-"Skip Database metrics from information schema missing in this version";
- return;
- }
-
- my @dblist = select_array("SHOW DATABASES;");
- infoprint "There is " . scalar(@dblist) . " Database(s).";
- my @totaldbinfo = split /\s/,
- select_one(
-"SELECT SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH) , SUM(DATA_LENGTH+INDEX_LENGTH) FROM information_schema.TABLES;"
- );
- infoprint "All Databases:";
- infoprint " +-- ROWS : "
- . ( $totaldbinfo[0] eq 'NULL' ? 0 : $totaldbinfo[0] ) . "";
- infoprint " +-- DATA : "
- . hr_bytes( $totaldbinfo[1] ) . "("
- . percentage( $totaldbinfo[1], $totaldbinfo[3] ) . "%)";
- infoprint " +-- INDEX: "
- . hr_bytes( $totaldbinfo[2] ) . "("
- . percentage( $totaldbinfo[2], $totaldbinfo[3] ) . "%)";
- infoprint " +-- SIZE : " . hr_bytes( $totaldbinfo[3] ) . "";
-
- badprint "Index size is larger than data size \n"
- if $totaldbinfo[1] < $totaldbinfo[2];
-
- $result{'Databases'}{'All databases'}{'Rows'} =
- ( $totaldbinfo[0] eq 'NULL' ? 0 : $totaldbinfo[0] );
- $result{'Databases'}{'All databases'}{'Data Size'} = $totaldbinfo[1];
- $result{'Databases'}{'All databases'}{'Data Pct'} =
- percentage( $totaldbinfo[1], $totaldbinfo[3] ) . "%";
- $result{'Databases'}{'All databases'}{'Index Size'} = $totaldbinfo[2];
- $result{'Databases'}{'All databases'}{'Index Pct'} =
- percentage( $totaldbinfo[2], $totaldbinfo[3] ) . "%";
- $result{'Databases'}{'All databases'}{'Total Size'} = $totaldbinfo[3];
-
- foreach (@dblist) {
- chomp($_);
- if ( $_ eq "information_schema"
- or $_ eq "performance_schema"
- or $_ eq "mysql"
- or $_ eq "" )
- {
- next;
- }
-
- my @dbinfo = split /\s/,
- select_one(
-"SELECT TABLE_SCHEMA, SUM(TABLE_ROWS), SUM(DATA_LENGTH), SUM(INDEX_LENGTH) , SUM(DATA_LENGTH+INDEX_LENGTH), COUNT(DISTINCT ENGINE) FROM information_schema.TABLES WHERE TABLE_SCHEMA='$_' GROUP BY TABLE_SCHEMA ORDER BY TABLE_SCHEMA"
- );
- next unless defined $dbinfo[0];
- infoprint "Database: " . $dbinfo[0] . "";
- infoprint " +-- ROWS : "
- . ( !defined( $dbinfo[1] ) or $dbinfo[1] eq 'NULL' ? 0 : $dbinfo[1] )
- . "";
- infoprint " +-- DATA : "
- . hr_bytes( $dbinfo[2] ) . "("
- . percentage( $dbinfo[2], $dbinfo[4] ) . "%)";
- infoprint " +-- INDEX: "
- . hr_bytes( $dbinfo[3] ) . "("
- . percentage( $dbinfo[3], $dbinfo[4] ) . "%)";
- infoprint " +-- TOTAL: " . hr_bytes( $dbinfo[4] ) . "";
- badprint "Index size is larger than data size for $dbinfo[0] \n"
- if $dbinfo[2] < $dbinfo[3];
- badprint "There " . $dbinfo[5] . " storage engines. Be careful \n"
- if $dbinfo[5] > 1;
- $result{'Databases'}{ $dbinfo[0] }{'Rows'} = $dbinfo[1];
- $result{'Databases'}{ $dbinfo[0] }{'Data Size'} = $dbinfo[2];
- $result{'Databases'}{ $dbinfo[0] }{'Data Pct'} =
- percentage( $dbinfo[2], $dbinfo[4] ) . "%";
- $result{'Databases'}{ $dbinfo[0] }{'Index Size'} = $dbinfo[3];
- $result{'Databases'}{ $dbinfo[0] }{'Index Pct'} =
- percentage( $dbinfo[3], $dbinfo[4] ) . "%";
- $result{'Databases'}{ $dbinfo[0] }{'Total Size'} = $dbinfo[4];
- }
-}
-
-# Recommandations for MySQL Databases
-sub mysql_indexes {
- return if ( $opt{idxstat} == 0 );
-
- prettyprint
-"\n-------- Indexes Metrics -------------------------------------------------";
- unless ( mysql_version_ge( 5, 5 ) ) {
- infoprint
-"Skip Index metrics from information schema missing in this version";
- return;
- }
- my $selIdxReq = <<'ENDSQL';
-SELECT
- CONCAT(CONCAT(t.TABLE_SCHEMA, '.'),t.TABLE_NAME) AS 'table'
- , CONCAT(CONCAT(CONCAT(s.INDEX_NAME, '('),s.COLUMN_NAME), ')') AS 'index'
- , s.SEQ_IN_INDEX AS 'seq'
- , s2.max_columns AS 'maxcol'
- , s.CARDINALITY AS 'card'
- , t.TABLE_ROWS AS 'est_rows'
- , ROUND(((s.CARDINALITY / IFNULL(t.TABLE_ROWS, 0.01)) * 100), 2) AS 'sel'
-FROM INFORMATION_SCHEMA.STATISTICS s
- INNER JOIN INFORMATION_SCHEMA.TABLES t
- ON s.TABLE_SCHEMA = t.TABLE_SCHEMA
- AND s.TABLE_NAME = t.TABLE_NAME
- INNER JOIN (
- SELECT
- TABLE_SCHEMA
- , TABLE_NAME
- , INDEX_NAME
- , MAX(SEQ_IN_INDEX) AS max_columns
- FROM INFORMATION_SCHEMA.STATISTICS
- WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')
- GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
- ) AS s2
- ON s.TABLE_SCHEMA = s2.TABLE_SCHEMA
- AND s.TABLE_NAME = s2.TABLE_NAME
- AND s.INDEX_NAME = s2.INDEX_NAME
-WHERE t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')
-AND t.TABLE_ROWS > 10
-AND s.CARDINALITY IS NOT NULL
-AND (s.CARDINALITY / IFNULL(t.TABLE_ROWS, 0.01)) < 8.00
-ORDER BY sel
-LIMIT 10;
-ENDSQL
- my @idxinfo = select_array($selIdxReq);
- infoprint "Worst selectivity indexes:";
- foreach (@idxinfo) {
- debugprint "$_";
- my @info = split /\s/;
- infoprint "Index: " . $info[1] . "";
-
- infoprint " +-- COLUNM : " . $info[0] . "";
- infoprint " +-- NB SEQS : " . $info[2] . " sequence(s)";
- infoprint " +-- NB COLS : " . $info[3] . " column(s)";
- infoprint " +-- CARDINALITY : " . $info[4] . " distinct values";
- infoprint " +-- NB ROWS : " . $info[5] . " rows";
- infoprint " +-- SELECTIVITY : " . $info[6] . "%";
-
- $result{'Indexes'}{ $info[1] }{'Colunm'} = $info[0];
- $result{'Indexes'}{ $info[1] }{'Sequence number'} = $info[2];
- $result{'Indexes'}{ $info[1] }{'Number of collunm'} = $info[3];
- $result{'Indexes'}{ $info[1] }{'Cardianality'} = $info[4];
- $result{'Indexes'}{ $info[1] }{'Row number'} = $info[5];
- $result{'Indexes'}{ $info[1] }{'Selectivity'} = $info[6];
- if ( $info[6] < 25 ) {
- badprint "$info[1] has a low selectivity";
- }
- }
-
- return
- unless ( defined( $myvar{'performance_schema'} )
- and $myvar{'performance_schema'} eq 'ON' );
-
- $selIdxReq = <<'ENDSQL';
-SELECT CONCAT(CONCAT(object_schema,'.'),object_name) AS 'table', index_name
-FROM performance_schema.table_io_waits_summary_by_index_usage
-WHERE index_name IS NOT NULL
-AND count_star =0
-AND index_name <> 'PRIMARY'
-AND object_schema != 'mysql'
-ORDER BY count_star, object_schema, object_name;
-ENDSQL
- @idxinfo = select_array($selIdxReq);
- infoprint "Unsused indexes:";
- push( @generalrec, "Remove unused indexes." ) if ( scalar(@idxinfo) > 0 );
- foreach (@idxinfo) {
- debugprint "$_";
- my @info = split /\s/;
- badprint "Index: $info[1] on $info[0] is not used.";
- push @{ $result{'Indexes'}{'Unused Indexes'} },
- $info[0] . "." . $info[1];
- }
-}
-
-# Take the two recommendation arrays and display them at the end of the output
-sub make_recommendations {
- prettyprint
-"\n-------- Recommendations -----------------------------------------------------";
- if ( @generalrec > 0 ) {
- prettyprint "General recommendations:";
- foreach (@generalrec) { prettyprint " " . $_ . ""; }
- }
- if ( @adjvars > 0 ) {
- prettyprint "Variables to adjust:";
- if ( $mycalc{'pct_max_physical_memory'} > 90 ) {
- prettyprint
- " *** MySQL's maximum memory usage is dangerously high ***\n"
- . " *** Add RAM before increasing MySQL buffer variables ***";
- }
- foreach (@adjvars) { prettyprint " " . $_ . ""; }
- }
- if ( @generalrec == 0 && @adjvars == 0 ) {
- prettyprint
- "No additional performance recommendations are available.";
- }
-}
-
-sub close_outputfile {
- close($fh) if defined($fh);
-}
-
-sub headerprint {
- prettyprint
- " >> MySQLTuner $tunerversion - Major Hayden \n"
- . " >> Bug reports, feature requests, and downloads at http://mysqltuner.com/\n"
- . " >> Run with '--help' for additional options and output filtering";
-}
-
-sub string2file {
- my $filename=shift;
- my $content=shift;
- open my $fh, q(>), $filename
- or die "Unable to open $filename in write mode. please check permissions for this file or directory";
- print $fh $content if defined($content);
- close $fh;
- debugprint $content if ($opt{'debug'});
-}
-
-sub file2array {
- my $filename = shift;
- debugprint "* reading $filename" if ($opt{'debug'});
- my $fh;
- open( $fh, q(<), "$filename" )
- or die "Couldn't open $filename for reading: $!\n";
- my @lines = <$fh>;
- close($fh);
- return @lines;
-}
-
-sub file2string {
- return join ( '', file2array(@_) );
-}
-
-my $templateModel;
-if ($opt{'template'} ne 0 ) {
- $templateModel=file2string ($opt{'template'});
-}else {
- # DEFAULT REPORT TEMPLATE
- $templateModel=<<'END_TEMPLATE';
-
-
-
- Report
-
-
-
-
-Result output
-
-{$data}
-
-
-
-
-END_TEMPLATE
-}
-sub dump_result {
- if ($opt{'debug'}) {
- use Data::Dumper qw/Dumper/;
- $Data::Dumper::Pair = " : ";
- debugprint Dumper( \%result );
- }
-
- debugprint "HTML REPORT: $opt{'reportfile'}";
- if ($opt{'reportfile'} ne 0 ) {
- use Data::Dumper qw/Dumper/;
- $Data::Dumper::Pair = " : ";
- my $vars= {'data' => Dumper( \%result ) };
-
- my $template = Text::Template->new(TYPE => 'STRING', PREPEND => q{;}, SOURCE => $templateModel)
- or die "Couldn't construct template: $Text::Template::ERROR";
- open my $fh, q(>), $opt{'reportfile'}
- or die "Unable to open $opt{'reportfile'} in write mode. please check permissions for this file or directory";
- $template->fill_in(HASH =>$vars, OUTPUT=>$fh );
- close $fh;
- }
-}
-
-# ---------------------------------------------------------------------------
-# BEGIN 'MAIN'
-# ---------------------------------------------------------------------------
-headerprint # Header Print
-mysql_setup; # Gotta login first
-validate_tuner_version; # Check last version
-os_setup; # Set up some OS variables
-get_all_vars; # Toss variables/status into hashes
-get_tuning_info; # Get information about the tuning connexion
-validate_mysql_version; # Check current MySQL version
-check_architecture; # Suggest 64-bit upgrade
-check_storage_engines; # Show enabled storage engines
-mysql_databases; # Show informations about databases
-mysql_indexes; # Show informations about indexes
-security_recommendations; # Display some security recommendations
-calculations; # Calculate everything we need
-mysql_stats; # Print the server stats
-mysql_myisam; # Print MyISAM stats
-mysql_innodb; # Print InnoDB stats
-mysql_ariadb; # Print AriaDB stats
-get_replication_status; # Print replication info
-make_recommendations; # Make recommendations based on stats
-dump_result; # Dump result if debug is on
-close_outputfile; # Close reportfile if needed
-
-# ---------------------------------------------------------------------------
-# END 'MAIN'
-# ---------------------------------------------------------------------------
-1;
-
-__END__
-
-=pod
-
-=encoding UTF-8
-
-=head1 NAME
-
- MySQLTuner 1.6.0 - MySQL High Performance Tuning Script
-
-=head1 IMPORTANT USAGE GUIDELINES
-
-To run the script with the default options, run the script without arguments
-Allow MySQL server to run for at least 24-48 hours before trusting suggestions
-Some routines may require root level privileges (script will provide warnings)
-You must provide the remote server's total memory when connecting to other servers
-
-=head1 CONNECTION AND AUTHENTIFICATION
-
- --host Connect to a remote host to perform tests (default: localhost)
- --socket Use a different socket for a local connection
- --port Port to use for connection (default: 3306)
- --user Username to use for authentication
- --pass Password to use for authentication
- --mysqladmin Path to a custom mysqladmin executable
- --mysqlcmd Path to a custom mysql executable
-
-=head1 PERFORMANCE AND REPORTING OPTIONS
-
- --skipsize Don't enumerate tables and their types/sizes (default: on)
- (Recommended for servers with many tables)
- --skippassword Don't perform checks on user passwords(default: off)
- --checkversion Check for updates to MySQLTuner (default: don't check)
- --forcemem Amount of RAM installed in megabytes
- --forceswap Amount of swap memory configured in megabytes
- --passwordfile Path to a password file list(one password by line)
-
-=head1 OUTPUT OPTIONS
- --silent Don't output anything on screen
- --nogood Remove OK responses
- --nobad Remove negative/suggestion responses
- --noinfo Remove informational responses
- --debug Print debug information
- --dbstat Print database information
- --idxstat Print index information
- --nocolor Don't print output in color
- --buffers Print global and per-thread buffer values
- --outputfile Path to a output txt file
- --reportfile Path to a report txt file
- --template Path to a template file
-
-=head1 PERLDOC
-
-You can find documentation for this module with the perldoc command.
-
- perldoc mysqltuner
-
-=head2 INTENALS
-
-L
-
- Internal documentation
-
-=head1 AUTHORS
-
-Major Hayden - major@mhtx.net
-
-=head1 CONTRIBUTORS
-
-=over 4
-
-=item *
-
-Matthew Montgomery
-
-=item *
-
-Paul Kehrer
-
-=item *
-
-Dave Burgess
-
-=item *
-
-Jonathan Hinds
-
-=item *
-
-Mike Jackson
-
-=item *
-
-Nils Breunese
-
-=item *
-
-Shawn Ashlee
-
-=item *
-
-Luuk Vosslamber
-
-=item *
-
-Ville Skytta
-
-=item *
-
-Trent Hornibrook
-
-=item *
-
-Jason Gill
-
-=item *
-
-Mark Imbriaco
-
-=item *
-
-Greg Eden
-
-=item *
-
-Aubin Galinotti
-
-=item *
-
-Giovanni Bechis
-
-=item *
-
-Bill Bradford
-
-=item *
-
-Ryan Novosielski
-
-=item *
-
-Michael Scheidell
-
-=item *
-
-Blair Christensen
-
-=item *
-
-Hans du Plooy
-
-=item *
-
-Victor Trac
-
-=item *
-
-Everett Barnes
-
-=item *
-
-Tom Krouper
-
-=item *
-
-Gary Barrueto
-
-=item *
-
-Simon Greenaway
-
-=item *
-
-Adam Stein
-
-=item *
-
-Isart Montane
-
-=item *
-
-Baptiste M.
-
-=item *
-
-Cole Turner
-
-=item *
-
-Major Hayden
-
-=item *
-
-Joe Ashcraft
-
-=item *
-
-Jean-Marie Renouard
-
-=back
-
-=head1 SUPPORT
-
-
-Bug reports, feature requests, and downloads at http://mysqltuner.com/
-
-Bug tracker can be found at https://github.com/major/MySQLTuner-perl/issues
-
-Maintained by Major Hayden (major\@mhtx.net) - Licensed under GPL
-
-=head1 SOURCE CODE
-
-L
-
- git clone -q https://github.com/major/MySQLTuner-perl.git
-
-=head1 COPYRIGHT AND LICENSE
-
-Copyright (C) 2006-2015 Major Hayden - major@mhtx.net
-
-For the latest updates, please visit http://mysqltuner.com/
-
-Git repository available at http://github.com/major/MySQLTuner-perl
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-
-=cut
-
-# Local variables:
-# indent-tabs-mode: t
-# cperl-indent-level: 8
-# perl-indent-level: 8
-# End:
diff --git a/scripts/remove_certbotle.sh b/scripts/remove_certbotle.sh
index d10b8417..2b9fddc1 100755
--- a/scripts/remove_certbotle.sh
+++ b/scripts/remove_certbotle.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function init_certbotle_removal() {
if dpkg-query -l | awk '/certbot/ { print $2 }' | grep -qwE "^certbot$"; then
diff --git a/scripts/remove_fail2ban.sh b/scripts/remove_fail2ban.sh
index 90b46d7d..989dfd80 100755
--- a/scripts/remove_fail2ban.sh
+++ b/scripts/remove_fail2ban.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function init_fail2ban_removal() {
# Stop fail2ban process.
diff --git a/scripts/remove_mailer.sh b/scripts/remove_mailer.sh
index 676f3776..ddd31377 100755
--- a/scripts/remove_mailer.sh
+++ b/scripts/remove_mailer.sh
@@ -14,4 +14,4 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
diff --git a/scripts/remove_mariadb.sh b/scripts/remove_mariadb.sh
index f47ffbf0..a334f9a0 100755
--- a/scripts/remove_mariadb.sh
+++ b/scripts/remove_mariadb.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function mariadb_remove_config() {
# Remove MariaDB server config files.
diff --git a/scripts/remove_memcached.sh b/scripts/remove_memcached.sh
index 18b30036..da1ebdaf 100755
--- a/scripts/remove_memcached.sh
+++ b/scripts/remove_memcached.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function init_memcached_removal() {
# Stop Memcached server process.
diff --git a/scripts/remove_mongodb.sh b/scripts/remove_mongodb.sh
index 67c17dad..5c398fdf 100755
--- a/scripts/remove_mongodb.sh
+++ b/scripts/remove_mongodb.sh
@@ -2,7 +2,7 @@
# MongoDB Uninstaller
# Min. Requirement : GNU/Linux Ubuntu 18.04
-# Last Build : 10/12/2021
+# Last Build : 24/12/2021
# Author : MasEDI.Net (me@masedi.net)
# Since Version : 1.0.0
@@ -14,28 +14,43 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
+
+# Make sure only supported distribution can run this installer script.
+preflight_system_check
+
+DISTRIB_NAME=${DISTRIB_NAME:-$(get_distrib_name)}
+RELEASE_NAME=${RELEASE_NAME:-$(get_release_name)}
+MONGODB_VERSION=${MONGODB_VERSION:-"5.0"}
+[[ "${RELEASE_NAME}" == "jessie" || "${RELEASE_NAME}" == "xenial" ]] && MONGODB_VERSION="4.4"
+
+function remove_mongodb_repo() {
+ echo "Removing MongoDB repository..."
+
+ if [[ -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list" ]]; then
+ run rm -f "/etc/apt/sources.list.d/mongodb-org-${MONGODB_VERSION}-${RELEASE_NAME}.list"
+ run apt-get update -qq -y
+ fi
+
+ echo "Removing MongoDB repository key..."
+
+ run bash -c "wget -qO - 'https://www.mongodb.org/static/pgp/server-${MONGODB_VERSION}.asc' | apt-key del -"
+}
function init_mongodb_removal() {
# Stop MongoDB server process.
if [[ $(pgrep -c mongod) -gt 0 ]]; then
+ echo "Stopping MongoDB server..."
+
run systemctl stop mongod
fi
if dpkg-query -l | awk '/mongodb/ { print $2 }' | grep -qwE "^mongodb"; then
- echo "Found MongoDB package installation. Removing..."
+ echo "Removing MongoDB packages..."
# Remove MongoDB server.
#shellcheck disable=SC2046
- #run apt-get purge -qq -y $(dpkg-query -l | awk '/mongodb/ { print $2 }')
- run apt-get purge -qq -y mongodb-org mongodb-org-server mongodb-org-shell mongodb-org-tools
-
- if [[ "${FORCE_REMOVE}" == true ]]; then
- run rm -f /etc/apt/sources.list.d/mongodb-org-*
- fi
-
- # Remove MongoDB config files.
- warning "!! This action is not reversible !!"
+ run apt-get purge -qq -y $(dpkg-query -l | awk '/mongodb/ { print $2 }')
if [[ "${AUTO_REMOVE}" == true ]]; then
if [[ "${FORCE_REMOVE}" == true ]]; then
@@ -44,27 +59,35 @@ function init_mongodb_removal() {
REMOVE_MONGOD_CONFIG="n"
fi
else
+ # Remove MongoDB config files.
+ warning "!! This action is not reversible !!"
+
while [[ "${REMOVE_MONGOD_CONFIG}" != "y" && "${REMOVE_MONGOD_CONFIG}" != "n" ]]; do
read -rp "Remove MongoDB database and configuration files? [y/n]: " -e REMOVE_MONGOD_CONFIG
done
fi
if [[ "${REMOVE_MONGOD_CONFIG}" == Y* || "${REMOVE_MONGOD_CONFIG}" == y* ]]; then
- [ -f /etc/mongod.conf ] && run rm -fr /etc/mongod.conf
+ echo "Removing MongoDB data & configs..."
+
+ [ -f /etc/mongod.conf ] && run rm -f /etc/mongod.conf
[ -d /var/lib/mongodb ] && run rm -fr /var/lib/mongodb
- echo "All your MongoDB database and configuration files deleted permanently."
+ #echo "All your MongoDB database and configuration files deleted permanently."
+
+ # Remove MongoDB repository.
+ remove_mongodb_repo
fi
else
echo "MongoDB package not found, possibly installed from source."
- echo "Remove it manually!!"
MONGOD_BIN=$(command -v mongod)
- echo "MongoDB server binary executable: ${MONGOD_BIN}"
+ echo "MongoDB server executable binary: ${MONGOD_BIN}"
+ echo "You could remove it manually!"
fi
- # Final test.
+ # Final check.
if [[ "${DRYRUN}" != true ]]; then
if [[ -z $(command -v mongod) ]]; then
success "MongoDB server removed succesfully."
@@ -76,7 +99,7 @@ function init_mongodb_removal() {
fi
}
-echo "Uninstalling MongoDB server..."
+echo "[MongoDB ${MONGODB_VERSION} Server Removal]"
if [[ -n $(command -v mongod) ]]; then
if [[ "${AUTO_REMOVE}" == true ]]; then
diff --git a/scripts/remove_nginx.sh b/scripts/remove_nginx.sh
index add88613..71b74569 100755
--- a/scripts/remove_nginx.sh
+++ b/scripts/remove_nginx.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
# Remove nginx.
function init_nginx_removal() {
diff --git a/scripts/remove_php.sh b/scripts/remove_php.sh
index 651eea3f..c94caa60 100755
--- a/scripts/remove_php.sh
+++ b/scripts/remove_php.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
##
# Remove PHP & FPM installation from system.
diff --git a/scripts/remove_redis.sh b/scripts/remove_redis.sh
index b7748a7c..246618a5 100755
--- a/scripts/remove_redis.sh
+++ b/scripts/remove_redis.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function init_redis_removal() {
# Stop Redis server process.
diff --git a/scripts/remove_vsftpd.sh b/scripts/remove_vsftpd.sh
index b2919ad1..73777ae6 100755
--- a/scripts/remove_vsftpd.sh
+++ b/scripts/remove_vsftpd.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
function init_vsftpd_removal() {
# Stop VSFTPD process.
diff --git a/scripts/secure_server.sh b/scripts/secure_server.sh
index eea58d21..beae00b9 100755
--- a/scripts/secure_server.sh
+++ b/scripts/secure_server.sh
@@ -14,7 +14,7 @@ if [[ "$(type -t run)" != "function" ]]; then
fi
# Make sure only root can run this installer script.
-requires_root
+requires_root "$@"
##
# Securing SSH server.