Compare commits

...

43 Commits

Author SHA1 Message Date
Alexey Berezhok
e991cf4797 Fixed changelog 2025-02-04 23:41:46 +03:00
Alexey Berezhok
66bb1323a9 Added support some webapp applications. Part 2 2025-02-04 23:35:17 +03:00
Alexey Berezhok
e4624d9398 Added support some webapp applications 2025-02-04 23:34:14 +03:00
Alexey Berezhok
b7e404e18c Update composer for new version of fm and brepo/phpquoteshellarg 2025-02-04 21:53:22 +03:00
Alexey Berezhok
316ca0e292 Added alternative php. Part 14 2025-02-02 23:48:28 +03:00
Alexey Berezhok
6e7af9ea42 Added alternative php. Part 13 2025-02-02 22:07:18 +03:00
Alexey Berezhok
06fa9cb9c2 Added alternative php. Part 12 2025-02-01 23:48:29 +03:00
Alexey Berezhok
93ccae3f18 Added alternative php. Part 11 2025-01-31 23:41:28 +03:00
Alexey Berezhok
14af530339 Added alternative php. Part 10 2025-01-31 00:10:16 +03:00
Alexey Berezhok
57594e1a76 Added alternative php. Part 9 2025-01-22 23:29:41 +03:00
Alexey Berezhok
c25c8d8f64 Added alternative php. Part 8 2025-01-22 23:10:51 +03:00
Alexey Berezhok
b29a369515 Added alternative php. Part 7 2025-01-19 23:52:30 +03:00
Alexey Berezhok
7f3b5fdd27 Added alternative php. Part 5 2025-01-19 22:17:36 +03:00
Alexey Berezhok
221fe29cf0 Added alternative php. Part 4 2025-01-19 22:11:40 +03:00
Alexey Berezhok
f3b9d33016 Use local php. Part 3 2025-01-18 15:55:12 +03:00
Alexey Berezhok
2f91eee76d Use local php. Part 2 2025-01-17 21:33:34 +03:00
Alexey Berezhok
66e574dd33 Use local php. Part 1 2025-01-13 23:21:50 +03:00
Alexey Berezhok
8e2a9e1f42 Added quota 2025-01-10 22:45:19 +03:00
Alexey Berezhok
f01015c05d quota fix. Part 1 2025-01-09 23:49:05 +03:00
Alexey Berezhok
60eac545d6 Remove debian and ubuntu installer 2025-01-08 23:01:10 +03:00
Alexey Berezhok
95a0e87271 Added sha-512 authorization fix 2025-01-07 15:27:17 +03:00
Alexey Berezhok
4c51952ee3 Added change log 2025-01-06 19:36:07 +03:00
Alexey Berezhok
7402364d0b Fixed congrats message 2025-01-06 19:25:46 +03:00
Alexey Berezhok
74d516f2ca Added minor fixes 2025-01-05 23:58:08 +03:00
Alexey Berezhok
7f969cf6bb Added minor fixes 2025-01-05 23:34:30 +03:00
Alexey Berezhok
f18ea4c808 Added small fixs 2025-01-05 22:18:59 +03:00
Alexey Berezhok
dba200787f Fixed passenger installation 2025-01-02 17:18:21 +03:00
Alexey Berezhok
56fab11941 Fix documentation links 2025-01-01 23:49:08 +03:00
Alexey Berezhok
62eb67af03 Added spec update and docs update 2024-12-31 00:10:03 +03:00
Alexey Berezhok
6bd321a1da Added passeneg manager. Part 12 2024-12-30 00:16:14 +03:00
Alexey Berezhok
5443ea44dd Added passeneg manager. Part 11 2024-12-28 23:41:32 +03:00
Alexey Berezhok
9036a02b5b Added passeneg manager. Part 10 2024-12-26 22:58:36 +03:00
Alexey Berezhok
c0efc35d34 Added passeneg manager. Part 9 2024-12-24 22:52:19 +03:00
Alexey Berezhok
0ecf0ee925 Added passeneg manager. Part 8 2024-12-23 23:42:58 +03:00
Alexey Berezhok
645cd8386a Added passeneg manager. Part 7 2024-12-21 22:16:33 +03:00
Alexey Berezhok
5067d35524 Added passeneg manager. Part 6 2024-12-19 23:15:04 +03:00
Alexey Berezhok
c572522f43 Added passeneg manager. Part 5 2024-12-17 23:47:00 +03:00
Alexey Berezhok
d3f7451c9b Added passeneg manager. Part 4 2024-12-15 23:47:27 +03:00
Alexey Berezhok
a2988a71d7 Added passeneg manager. Part 3 2024-12-14 23:10:43 +03:00
Alexey Berezhok
455223af4b Added passeneg manager. Part 2 2024-12-13 23:31:05 +03:00
Alexey Berezhok
4a10c586e1 Added passenger_manager commands 2024-12-11 23:46:22 +03:00
Alexey Berezhok
4905975d79 Added ruby manager. Partial 2024-12-09 23:55:35 +03:00
Alexey Berezhok
d0da95dfc5 Added passenger support. Partialy 1 2024-12-03 21:44:39 +03:00
184 changed files with 15863 additions and 15312 deletions

View File

@@ -2,6 +2,25 @@
All notable changes to this project will be documented in this file.
## [1.9.5.rpm] - Release
- Added support installation of alternative php not only remi
- Fixed separate edition of php.ini in multiphp mode
## [1.9.4.rpm] - Release
- Fixed sha-512 auth in hestiacp
- Added quota support for rpm based os
## [1.9.2.rpm] - Release
- Forked from 1.8.6 alpha and reworked for rpm based systems support
- Added passenger support (https://hestiadocs.brepo.ru/docs/extensions/extended-modules.html#passenger-manager)
- Added unified proxy templates support (https://hestiadocs.brepo.ru/docs/user-guide/web-domains.html#шаблоны-прокси)
- Added php-cli-selector (https://hestiadocs.brepo.ru/docs/extensions/php-cli-selector.html#php-cli-selector)
- Added alternative extensions support (https://hestiadocs.brepo.ru/docs/extensions/php-cli-selector.html#php-cli-selector)
- Added russian documentation (https://hestiadocs.brepo.ru/docs/introduction/getting-started.html)
## [1.8.6] - Alpha release
- Added rpm systems support

View File

@@ -1,110 +1,102 @@
<h1 align="center">Hestia Control Panel</h1>
<h1 align="center">Hestia Control Panel (RPM Edition)</h1>
<h2 align="center">Lightweight and powerful control panel for the modern web</h2>
<p align="center"><strong>Original project:</strong> | <a href="https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md">View Changelog</a> |
<a href="https://www.hestiacp.com/">HestiaCP.com</a> |
<a href="https://docs.hestiacp.com/">Documentation</a> |
<a href="https://forum.hestiacp.com/">Forum</a>
<br/><br/></p>
<h2 align="center">Легкая и мощная панель управления для современного сервера. Организуй собственный сервер в два счета.</h2>
<p align="center"><strong>Ссылки на оригинальный проект для Ubuntu и Debian:</strong> | <a href="https://www.hestiacp.com/">HestiaCP.com</a> |
</p>
<p align="center">
<strong>RPM support project:</strong> |
<strong>Информация по RPM Edition сборке:</strong> |
<a href="https://hestiadocs.brepo.ru/">Documentation for version with RPM support</a>
</p>
## **Welcome!**
Hestia Control Panel (RPM Edition) поддерживается и дорабатывается отдельной командой связанной с RPM Based операционными системаи, с момента форка от оригинального, данный проект включил изменения, которые не позволяют просто подтягивать доработки из оригинального проекта (и не все доработки Ubuntu и Debian нужны в RPM Based системах). Поэтому все изменения из оригинальной Hestia CP не подтягиваются автоматически, поэтому о найденных ошибках в текущей реализации необходимо репортить в текущий проект.
Hestia Control Panel is designed to provide administrators an easy to use web and command line interface, enabling them to quickly deploy and manage web domains, mail accounts, DNS zones, and databases from one central dashboard without the hassle of manually deploying and configuring individual components or services.
Ниже общее описание панели.
## Features and Services
## **Добро пожаловать!**
- Apache2 and NGINX with PHP-FPM
- Multiple PHP versions (5.6 - 8.2, 8.0 as default)
- DNS Server (Bind) with clustering capabilities
- POP/IMAP/SMTP mail services with Anti-Virus, Anti-Spam, and Webmail (ClamAV, SpamAssassin, Sieve, Roundcube)
- MariaDB/MySQL and/or PostgreSQL databases
- Let's Encrypt SSL support with wildcard certificates
- Firewall with brute-force attack detection and IP lists (iptables, fail2ban, and ipset).
Панель управления Hestia предназначена для предоставления администраторам простого в использовании веб-интерфейса и интерфейса командной строки, что позволяет им быстро развертывать веб-домены, почтовые аккаунты, зоны DNS и базы данных и управлять ими с единой центральной панели без необходимости вручную развертывать и настраивать отдельные компоненты или сервисы.
## Supported platforms and operating systems
## Функции и сервисы
- Apache2 и NGINX с PHP-FPM
- Несколько версий PHP (7.4 — 8.2, 8.0 по умолчанию, как из Remi репозитория, так и дополнительная самостоятельная сборка PHP пакетов)
- DNS-сервер (Bind)
- почтовые сервисы POP/IMAP/SMTP с защитой от вирусов, спама и веб-почтой (ClamAV, SpamAssassin, Sieve, Roundcube)
- базы данных MariaDB/MySQL и/или PostgreSQL
- поддержка SSL Let's Encrypt
- брандмауэр с защитой от атак методом перебора и списками IP (iptables, fail2ban и ipset).
## Поддерживаемые ОС
- **MSVSphere:** 9
- **AlmaLinux:** 9
- **RockyLinux:** 9
Currently stayed support of Debian and Ubuntu, but new functional will be available only for RPM based systems. For full supportin of Debian and Ubuntu use original [HestiaCP](https://github.com/hestiacp/hestiacp)
**ПРИМЕЧАНИЯ:**
**NOTES:**
- Панель управления Hestia не поддерживает 32-разрядные операционные системы!
- Панель управления Hestia в сочетании с OpenVZ 7 или более ранними версиями может иметь проблемы с DNS и/или брандмауэром. Если вы используете виртуальный частный сервер, мы настоятельно рекомендуем использовать что-то на основе KVM или LXC!
- Hestia Control Panel does not support 32 bit operating systems!
- Hestia Control Panel in combination with OpenVZ 7 or lower might have issues with DNS and/or firewall. If you use a Virtual Private Server we strongly advice you to use something based on KVM or LXC!
## Установка панели управления Hestia
## Installing Hestia Control Panel
- **ПРИМЕЧАНИЕ:** для обеспечения правильной работы необходимо установить панель управления Hestia поверх новой операционной системы.
- **NOTE:** You must install Hestia Control Panel on top of a fresh operating system installation to ensure proper functionality.
Несмотря на то, что мы приложили все усилия, чтобы сделать процесс установки и интерфейс панели управления максимально удобными (даже для новых пользователей), предполагается, что вы уже обладаете некоторыми базовыми знаниями и пониманием того, как настроить сервер Linux, прежде чем продолжить.
While we have taken every effort to make the installation process and the control panel interface as friendly as possible (even for new users), it is assumed that you will have some prior knowledge and understanding in the basics how to set up a Linux server before continuing.
### Шаг 1. Войдите в систему
### Step 1: Log in
To start the installation, you will need to be logged in as **root** or a user with super-user privileges. You can perform the installation either directly from the command line console or remotely via SSH:
Чтобы начать установку, вам нужно войти в систему как **root** или пользователь с правами суперпользователя. Вы можете выполнить установку непосредственно из командной строки или удалённо через SSH:
```bash
ssh root@your.server
```
### Step 2: Download
### Шаг 2. Загрузка
Download the installation script for the latest release:
Загрузите установочный скрипт для последней версии:
```bash
wget https://dev.brepo.ru/bayrepo/hestiacp/raw/branch/master/install/hst-install.sh
```
If the download fails due to an SSL validation error, please be sure you've installed the ca-certificate package on your system - you can do this with the following command:
### Шаг 3: Запустите
```bash
yum update
```
### Step 3: Run
To begin the installation process, simply run the script and follow the on-screen prompts:
Чтобы начать процесс установки, просто запустите скрипт и следуйте инструкциям на экране:
```bash
bash hst-install.sh
```
You will receive a welcome email at the address specified during installation (if applicable) and on-screen instructions after the installation is completed to log in and access your server.
После завершения установки вы получите приветственное электронное письмо на адрес, указанный во время установки (если применимо), и инструкции на экране для входа в систему и доступа к вашему серверу.
### Custom installation
### Пользовательская установка
You may specify a number of various flags during installation to only install the features in which you need. To view a list of available options, run:
Во время установки вы можете указать несколько различных флагов, чтобы установить только те функции, которые вам нужны. Чтобы просмотреть список доступных опций, выполните:
```bash
bash hst-install.sh -h
```
## How to upgrade an existing installation
## Как обновить существующую установку
Automatic Updates are enabled by default on new installations of Hestia Control Panel and can be managed from **Server Settings > Updates**. To manually check for and install available updates, use the system package manager:
Автоматические обновления включены по умолчанию в новых установках Hestia Control Panel, и ими можно управлять из **Server Settings > Updates**. Чтобы вручную проверить наличие доступных обновлений и установить их, воспользуйтесь системным менеджером пакетов:
```bash
dnf update
```
## Issues & Support Requests
## Проблемы и запросы в службу поддержки
- If you encounter a general problem while using Hestia Control Panel for RPM based system use [issue report](https://github.com/bayrepo/hestiacp/issues)
- Если вы столкнулись с общей проблемой при использовании Hestia Control Panel для системы на основе RPM, воспользуйтесь [отчётом о проблеме](https://github.com/bayrepo/hestiacp-rpm/issues)
For original HestiaCP for Debian and Ubuntu use [original version](https://github.com/hestiacp/hestiacp):
Для оригинальной HestiaCP для Debian и Ubuntu используйте [оригинальную версию](https://github.com/hestiacp/hestiacp):
## Copyright
## Авторские права
See original copyright of [HestiaCP](https://github.com/hestiacp/hestiacp)
Ознакомьтесь с оригинальными авторскими правами [HestiaCP](https://github.com/hestiacp/hestiacp)
## License
## Лицензия
Hestia Control Panel is licensed under [GPL v3](https://github.com/hestiacp/hestiacp/blob/release/LICENSE) license, and is based on the [VestaCP](https://vestacp.com/) project.<br>
Панель управления Hestia распространяется по лицензии [GPL v3](https://github.com/hestiacp/hestiacp/blob/release/LICENSE) и основана на проекте [VestaCP](https://vestacp.com/).<br>

View File

@@ -21,28 +21,10 @@ source_conf "$HESTIA/conf/hestia.conf"
# Verifications #
#----------------------------------------------------------#
# Ensure that quota kernel modules are installed
if [ ! -f /etc/redhat-release ]; then
kernel_module_check=$(find /lib/modules/$(uname -r) -type f -name '*quota_v*.ko*' | egrep '.*' && [ $? -eq 0 ])
if [ -z "$kernel_module_check" ]; then
# Install kernel modules for quota support.
# Requires reboot to activate updated kernel.
echo "Installing required kernel modules for quota support..."
reboot_req="Y"
apt-get -qq install linux-image-extra-virtual -y
check_result $? "kernel module installation failed" "$E_UPDATE"
fi
fi
# Checking quota package
quota=$(which --skip-alias --skip-functions quota 2> /dev/null)
if [ $? -ne 0 ]; then
if [ -f "/etc/redhat-release" ]; then
dnf -y install quota > /dev/null 2>&1
else
export DEBIAN_FRONTEND=noninteractive
apt-get -y install quota > /dev/null 2>&1
fi
dnf -y install quota > /dev/null 2>&1
check_result $? "quota package installation failed" "$E_UPDATE"
fi
@@ -54,34 +36,70 @@ check_hestia_demo_mode
#----------------------------------------------------------#
# Adding group and user quota on /home partition
file_system=$(df -T /home | tail -n1 | awk '{print $2}')
mnt=$(df -P /home | awk '{print $6}' | tail -n1)
lnr=$(cat -n /etc/fstab | grep -v "#" | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ')
opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}')
fnd='usrquota\|grpquota\|usrjquota=aquota.user\|grpjquota=aquota.group\|jqfmt=vfsv0'
if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 5 ]; then
old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=') | tr ' ' ',')
new='usrquota,grpquota,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0'
sed -i "$lnr s/$opt/$old,$new/" /etc/fstab
mount -o remount "$mnt"
if [ "$file_system" == "xfs" ]; then
fnd='usrquota\|grpquota'
if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 2 ]; then
old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota') | tr ' ' ',')
new='usrquota,grpquota'
sed -i "$lnr s/$opt/$old,$new/" /etc/fstab
mount -o remount "$mnt"
systemctl daemon-reload
if [ "$mnt" == "/" ]; then
check_args=$(grubby --info=ALL | grep -oP "rootflags=\S*")
if [ -n "$check_args" ]; then
RED='\033[0;31m'
NC='\033[0m'
YELLOW='\033[1;33m'
printf "${RED}!!!!!!!Detected rootflags in grub!!!!!!!${NC}\n"
echo "${YELLOW}Add manualy 'uquota,pquota' and reboot the system${NC}\n"
else
grubby --args="rootflags=uquota,pquota" --update-kernel=ALL
fi
fi
fi
elif [ "$file_system" == "ext4" ]; then
fnd='usrquota\|grpquota\|usrjquota=aquota.user\|grpjquota=aquota.group\|jqfmt=vfsv0'
if [ $(echo $opt | tr ',' '\n' | grep -x $fnd | wc -l) -ne 5 ]; then
old=$(echo $(echo $opt | tr ',' '\n' | grep -v 'usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt=') | tr ' ' ',')
new='usrquota,grpquota,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0'
sed -i "$lnr s/$opt/$old,$new/" /etc/fstab
mount -o remount "$mnt"
systemctl daemon-reload
fi
else
if [ -n "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then
sed -i "s/DISK_QUOTA=.*/DISK_QUOTA='no'/g" $HESTIA/conf/hestia.conf
fi
$BIN/v-log-action "system" "Info" "Plugins" "System Quota not supported."
log_history "system quota not supported"
log_event "$E_DISK" "$ARGUMENTS"
exit
fi
# Adding v2 group and user quota index
if [ ! -e "$mnt/aquota.user" ] || [ ! -e "$mnt/aquota.group" ]; then
quotacheck -avcugm > /dev/null 2>&1
fi
if [ "$file_system" == "ext4" ]; then
# Adding v2 group and user quota index
if [ ! -e "$mnt/aquota.user" ] || [ ! -e "$mnt/aquota.group" ]; then
quotacheck -avcugm > /dev/null 2>&1
fi
# Adding quotacheck on reboot
touch /forcequotacheck
# Adding quotacheck on reboot
touch /forcequotacheck
# Adding cron job
echo '#!/bin/bash' > /etc/cron.daily/quotacheck
echo 'touch /forcequotacheck' >> /etc/cron.daily/quotacheck
chmod a+x /etc/cron.daily/quotacheck
# Adding cron job
echo '#!/bin/bash' > /etc/cron.daily/quotacheck
echo 'touch /forcequotacheck' >> /etc/cron.daily/quotacheck
chmod a+x /etc/cron.daily/quotacheck
# Enabling group and user quota
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is off')" ]; then
quotaon -v $mnt
check_result $? "quota can't be enabled in $mnt" "$E_DISK"
fi
# Enabling group and user quota
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is off')" ]; then
quotaon -v $mnt
check_result $? "quota can't be enabled in $mnt" "$E_DISK"
fi
# Updating hestia.conf value

View File

@@ -14,6 +14,10 @@
user=$1
restart=$2
if [ "$user" == "puppet" ]; then
exit
fi
# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf

View File

@@ -111,6 +111,7 @@ $BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/cgi-bin"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/stats"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/logs"
$BIN/v-add-fs-directory "$user" "$HOMEDIR/$user/web/$domain/private/tmp"
# Creating domain logs
touch /var/log/$WEB_SYSTEM/domains/$domain.bytes \

View File

@@ -22,11 +22,11 @@ source $HESTIA/func/main.sh
source_conf "$HESTIA/conf/hestia.conf"
source_conf "$HESTIA/install/upgrade/upgrade.conf"
if [ -f /etc/redhat-release ]; then
for elem in "${!multiphp_v[@]}"; do
multiphp_v[$elem]=$(convert_dot_version_to_non_dot "${multiphp_v[$elem]}")
done
fi
for elem in "${!multiphp_v[@]}"; do
multiphp_v[$elem]=$(convert_dot_version_to_non_dot "${multiphp_v[$elem]}")
done
#----------------------------------------------------------#
# Verifications #
#----------------------------------------------------------#
@@ -38,27 +38,22 @@ if [ -z "$WEB_BACKEND" ]; then
fi
# Set file locations
if [ -f /etc/redhat-release ]; then
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
php_fpm=""
if [ "$LOCAL_PHP" == "yes" ]; then
php_fpm="/usr/lib/systemd/system/brepo-php-fpm$version.service"
else
php_fpm="/etc/init.d/php$version-fpm"
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
fi
# Verify php version format
if [ -f /etc/redhat-release ]; then
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
else
if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]."
echo "Example: 7.0, 7.4, 8.0"
exit "$E_INVALID"
fi
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
# Check if php version already exists
if [ -f "$php_fpm" ] && [ -f "$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl" ]; then
echo "ERROR: Specified PHP version is already installed."
@@ -77,48 +72,48 @@ check_hestia_demo_mode
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
mph=""
php_modules_install="mysqlnd mysqli pdo_mysql pgsql pdo sqlite pdo_sqlite pdo_pgsql imap ldap zip opcache xmlwriter xmlreader gd intl pspell"
php_modules_disable=""
if [ "$LOCAL_PHP" == "yes" ]; then
mph="brepo-php$version brepo-php$version-fpm"
if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then
php_modules_install=$(echo "$php_modules_install" | sed -e "s/pgsql//")
php_modules_install=$(echo "$php_modules_install" | sed -e "s/pdo_pgsql//")
php_modules_disable="$php_modules_disable pgsql pdo_pgsql"
fi
else
# Packages in Remi repo have names with php$version-php- prefixes
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
if [ "$version" = "56" ]; then
mph=$(sed -e "s/php$version-php-pecl-apcu//")
fi
mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl
php$version-fpm php$version-gd php$version-intl php$version-mysql
php$version-soap php$version-xml php$version-zip php$version-json php$version-bz2
php$version-pspell php$version-imagick php$version-pgsql php$version-imap php$version-ldap"
if [ -f /etc/redhat-release ]; then
# Packages in Remi repo have names with php$version-php- prefixes
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
if [ "$version" = "56" ]; then
mph=$(sed -e "s/php$version-php-pecl-apcu//")
fi
fi
# Check is version is 7.1 or below to add mcrypt
if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then
mph="$mph php$version-mcrypt"
fi
# Check is version is 7.1 or below to add mcrypt
if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then
mph="$mph php$version-mcrypt"
fi
# Check if version is 8.0 or higher and drop php json.
if [[ ${version:0:1} == "8" ]]; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-json//")
fi
# Check if version is 8.0 or higher and drop php json.
if [[ ${version:0:1} == "8" ]]; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-json//")
fi
if ! echo "$DB_SYSTEM" | grep -w 'mysql' > /dev/null; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-mysql//")
fi
if ! echo "$DB_SYSTEM" | grep -w 'mysql' > /dev/null; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-mysql//")
fi
if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-pgsql//")
if ! echo "$DB_SYSTEM" | grep -w 'pgsql' > /dev/null; then
mph=$(echo "$mph" | sed -e "s/php$version\(-php\)\{0,1\}-pgsql//")
fi
fi
# Install php packages
if [ -f '/etc/redhat-release' ]; then
dnf install -q -y $mph > /dev/null 2>&1 &
else
apt-get -qq update
apt-get -y -qq -o Dpkg::Options::="--force-confold" install $mph > /dev/null 2>&1 &
fi
dnf install -q -y $mph > /dev/null 2>&1 &
BACK_PID=$!
# Check if package installation is done, print a spinner
@@ -133,17 +128,27 @@ done
# Do a blank echo to get the \n back
echo
if [ "$LOCAL_PHP" == "yes" ]; then
for mod in $php_modules_install; do
enable_local_php_extension "$version" "$mod"
done
for mod in $php_modules_disable; do
disable_local_php_extension "$version" "$mod"
done
fi
# Check if installation was successful
if [ ! -f "$php_fpm" ]; then
echo "ERROR: Installation failed, please run the following command manually for debugging:"
if [ -f '/etc/redhat-release' ]; then
echo "dnf install $mph"
else
echo "apt-get install $mph"
fi
echo "dnf install $mph"
fi
if [ -f '/etc/redhat-release' ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
result_alt_php=$(alternatives --display php | grep /opt/brepo/php${version}/bin/php)
if [ -z "$result_alt_php" ]; then
alternatives --install /usr/bin/php php /opt/brepo/php${version}/bin/php 1 > /dev/null 2>&1
fi
else
result_alt_php=$(alternatives --display php | grep /usr/bin/php$version)
if [ -z "$result_alt_php" ]; then
alternatives --install /usr/bin/php php /usr/bin/php$version 1 > /dev/null 2>&1
@@ -173,7 +178,17 @@ fi
# Configure fpm
v_tpl=${version//./}
if [ -f /etc/redhat-release ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
systemctl enable brepo-php-fpm${version}.service
rm -f /opt/brepo/php${version}/etc/php-fpm.d/*
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /opt/brepo/php${version}/etc/php-fpm.d/
sed -i "s/9999/99$v_tpl/g" /opt/brepo/php${version}/etc/php-fpm.d/dummy.conf
# Increase max upload and max post size
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /opt/brepo/php${version}/etc/php.ini
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /opt/brepo/php${version}/etc/php.ini
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /opt/brepo/php${version}/etc/php.ini
else
systemctl enable php${version}-php-fpm
rm -f /etc/opt/remi/php${version}/php-fpm.d/*
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/opt/remi/php${version}/php-fpm.d/
@@ -183,19 +198,8 @@ if [ -f /etc/redhat-release ]; then
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/opt/remi/php${version}/php.ini
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/opt/remi/php${version}/php.ini
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/opt/remi/php${version}/php.ini
else
update-rc.d php$version-fpm defaults > /dev/null 2>&1
rm -f /etc/php/$version/fpm/pool.d/*
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/php/$version/fpm/pool.d/
sed -i "s/9999/99$v_tpl/g" /etc/php/$version/fpm/pool.d/dummy.conf
cp -f $HESTIA_INSTALL_DIR/php-fpm/php-fpm.conf /etc/php/$version/fpm/
sed -i "s/fpm_v/$version/g" /etc/php/$version/fpm/php-fpm.conf
# Increase max upload and max post size
sed -i "s/upload_max_filesize = 2M/upload_max_filesize = 100M/g" /etc/php/$version/fpm/php.ini
sed -i "s/post_max_size = 8M/post_max_size = 100M/g" /etc/php/$version/fpm/php.ini
sed -i "s/max_execution_time = 30/max_execution_time = 60/g" /etc/php/$version/fpm/php.ini
fi
# Install backend template
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl \
$HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl

View File

@@ -21,18 +21,10 @@ source_conf "$HESTIA/conf/hestia.conf"
check_args '1' "$#" 'VERSION'
# Verify php version format
if [ -f /etc/redhat-release ]; then
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
else
if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9].[0-9]."
echo "Example: 7.0, 7.4, 8.0"
exit "$E_INVALID"
fi
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The specified PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
# Check if php version exists
@@ -50,18 +42,19 @@ check_hestia_demo_mode
#----------------------------------------------------------#
# Set file locations
if [ -f /etc/redhat-release ]; then
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
php_fpm=""
if [ "$LOCAL_PHP" == "yes" ]; then
php_fpm="/usr/lib/systemd/system/brepo-php-fpm$version.service"
else
php_fpm="/etc/init.d/php$version-fpm"
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
fi
if [ -f /etc/redhat-release ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
rm -f /opt/brepo/php*/etc/php-fpm.d/www.conf
cp -f $HESTIA/install/rpm/php-fpm/www.conf /opt/brepo/php${version}/etc/php-fpm.d/www.conf
else
rm -f /etc/opt/remi/php*/php-fpm.d/www.conf
cp -f $HESTIA/install/rpm/php-fpm/www.conf /etc/opt/remi/php$version/php-fpm.d/www.conf
else
rm -f /etc/php/*/fpm/pool.d/www.conf
cp -f $HESTIA/install/deb/php-fpm/www.conf /etc/php/$version/fpm/pool.d/www.conf
fi
for user in $($BIN/v-list-sys-users plain); do
@@ -75,17 +68,30 @@ $BIN/v-restart-web-backend
$BIN/v-restart-web
$BIN/v-restart-proxy
if [ -f '/etc/redhat-release' ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
result_alt_php=$(alternatives --display php | grep /opt/brepo/php${version}/bin/php)
if [ -z "$result_alt_php" ]; then
alternatives --install /usr/bin/php php /opt/brepo/php${version}/bin/php 1 > /dev/null 2>&1
fi
else
result_alt_php=$(alternatives --display php | grep /usr/bin/php$version)
if [ -z "$result_alt_php" ]; then
alternatives --install /usr/bin/php php /usr/bin/php$version 1 > /dev/null 2>&1
fi
fi
update-alternatives --set php /usr/bin/php$version
if [ $? -eq 0 ]; then
update-alternatives --install /usr/bin/php php /usr/bin/php$version 1
if [ "$LOCAL_PHP" == "yes" ]; then
update-alternatives --set php /opt/brepo/php${version}/bin/php
if [ $? -eq 0 ]; then
update-alternatives --install /usr/bin/php php /opt/brepo/php${version}/bin/php 1
update-alternatives --set php /opt/brepo/php${version}/bin/php
fi
else
update-alternatives --set php /usr/bin/php$version
if [ $? -eq 0 ]; then
update-alternatives --install /usr/bin/php php /usr/bin/php$version 1
update-alternatives --set php /usr/bin/php$version
fi
fi
/usr/bin/hestiacp-php-admin system $version

View File

@@ -40,6 +40,28 @@ check_hestia_demo_mode
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
php_v="82"
if [[ "$service" =~ ^php ]];then
ver_php=$(echo "$service" | grep -Po "\d+")
if [ -z "$ver_php" ]; then
php_v=$(get_system_default_php)
else
if [ "$LOCAL_PHP" == "yes" ]; then
if [ -e "/opt/brepo/php${ver_php}" ]; then
php_v="$ver_php"
else
php_v=$(get_system_default_php)
fi
else
if [ -e "/etc/opt/remi/php${ver_php}" ]; then
php_v="$ver_php"
else
php_v=$(get_system_default_php)
fi
fi
fi
service="php"
fi
# Defining dst config path
case $service in
@@ -50,7 +72,13 @@ case $service in
exim4) dst='/etc/exim4/exim4.conf.template' ;;
vsftpd) dst=$(find /etc/vsftpd* -name 'vsftpd.conf') ;;
proftpd) dst=$(find /etc/proftpd* -name 'proftpd.conf') ;;
php) dst=$(find /etc/php* -name php.ini) ;;
php)
if [ "$LOCAL_PHP" == "yes" ]; then
dst=$(find /opt/brepo/php${php_v} -name php.ini)
else
dst=$(find /etc/opt/remi/php${php_v} -name php.ini)
fi
;;
mysql) dst=$(find /etc/my* -name my.cnf) ;;
mysqld) dst=$(find /etc/my* -name my.cnf) ;;
mariadb) dst=$(find /etc/my* -name my.cnf) ;;
@@ -103,7 +131,7 @@ if [ "$update" = 'yes' ] && [ "$restart" != 'no' ]; then
if [ "$service" = 'php' ]; then
if [ "$(multiphp_count)" -gt 0 ]; then
service="php-fpm"
elif [ "$WEB_SYSTEM" = 'apache2' ]; then
elif [ "$WEB_SYSTEM" = 'httpd' ]; then
service="$WEB_SYSTEM"
fi
fi

View File

@@ -30,32 +30,54 @@ check_hestia_demo_mode
#----------------------------------------------------------#
# Deleting group and user quota on /home partition
file_system=$(df -T /home | tail -n1 | awk '{print $2}')
mnt=$(df -P /home | awk '{print $6}' | tail -n1)
lnr=$(cat -n /etc/fstab | awk '{print $1,$3}' | grep "$mnt$" | cut -f 1 -d ' ')
opt=$(sed -n ${lnr}p /etc/fstab | awk '{print $4}')
fnd='usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt='
if [ -n "$(echo $opt | grep $fnd)" ]; then
rep=$(echo $(echo $opt | tr ',' '\n' | grep -v $fnd) | tr ' ' ',')
sed -i "$lnr s/$opt/$rep/" /etc/fstab
mount -o remount "$mnt"
fi
# Disabling group and user quota
quotaoff=$(which --skip-alias --skip-functions quotaoff 2> /dev/null)
if [ $? -eq 0 ]; then
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is on')" ]; then
$quotaoff $mnt
if [ "$file_system" == "xfs" ]; then
fnd='usrquota\|grpquota'
if [ -n "$(echo $opt | grep $fnd)" ]; then
rep=$(echo $(echo $opt | tr ',' '\n' | grep -v $fnd) | tr ' ' ',')
sed -i "$lnr s/$opt/$rep/" /etc/fstab
mount -o remount "$mnt"
fi
if [ "$mnt" == "/" ]; then
check_args=$(grubby --info=`grubby --default-kernel` | grep -oP "rootflags=[^\"]*" | head -n1)
if [ "$check_args" != "rootflags=uquota,pquota" ]; then
RED='\033[0;31m'
NC='\033[0m'
YELLOW='\033[1;33m'
printf "${RED}!!!!!!!Delete uquota,pquota from grub!!!!!!!${NC}\n"
echo "${YELLOW}Delete manualy 'uquota,pquota' and reboot the system${NC}\n"
else
grubby --remove-args="rootflags=uquota,pquota" --update-kernel=ALL
fi
fi
else
fnd='usrquota\|grpquota\|usrjquota=\|grpjquota=\|jqfmt='
if [ -n "$(echo $opt | grep $fnd)" ]; then
rep=$(echo $(echo $opt | tr ',' '\n' | grep -v $fnd) | tr ' ' ',')
sed -i "$lnr s/$opt/$rep/" /etc/fstab
mount -o remount "$mnt"
fi
# Disabling group and user quota
quotaoff=$(which --skip-alias --skip-functions quotaoff 2> /dev/null)
if [ $? -eq 0 ]; then
if [ -n "$(quotaon -pa | grep " $mnt " | grep 'user\|group' | grep 'is on')" ]; then
$quotaoff $mnt
fi
fi
# Deleting v1 + v2 group and user quota index
for idx in $(echo 'quota.user quota.group aquota.user aquota.group'); do
[ -e "$mnt/$idx" ] && rm -f "$mnt/$idx"
done
# Deleting cron job
rm -f /etc/cron.daily/quotacheck
fi
# Deleting v1 + v2 group and user quota index
for idx in $(echo 'quota.user quota.group aquota.user aquota.group'); do
[ -e "$mnt/$idx" ] && rm -f "$mnt/$idx"
done
# Deleting cron job
rm -f /etc/cron.daily/quotacheck
# Updating hestia.conf value
if [ -z "$(grep DISK_QUOTA $HESTIA/conf/hestia.conf)" ]; then
echo "DISK_QUOTA='no'" >> $HESTIA/conf/hestia.conf

View File

@@ -146,6 +146,18 @@ if [[ $BACKEND =~ ^.*PHP-([0-9])\_([0-9])$ ]]; then
else
version=$(multiphp_default_version)
fi
# Delete ruby if exists
if [ -e /usr/local/hestia/bin/v-ext-modules ]; then
res=$(/usr/local/hestia/bin/v-ext-modules state passenger_manager csv | tail -n 1 | /usr/bin/xargs | cut -d"," -f6 )
if [ -n "$res" ]; then
enabled=$(echo "$res" | grep enabled)
if [ -n "$enabled" ]; then
/usr/local/hestia/bin/v-ext-modules-run passenger_manager disable_user "$domain"
fi
fi
fi
# Restarting web server
$BIN/v-restart-web "$restart"
check_result $? "Web restart failed" > /dev/null

View File

@@ -52,11 +52,13 @@ get_domain_values 'web'
BACKEND="$template"
# Defining pool directory
if [ -f "/etc/redhat-release" ]; then
pool=$(find -L /etc/opt/remi/ -name "$domain.conf" -exec dirname {} \;)
pool=""
if [ "$LOCAL_PHP" == "yes" ]; then
pool=$(find -L /opt/brepo/ -name "$domain.conf" -exec dirname {} \;)
else
pool=$(find -L /etc/php/ -name "$domain.conf" -exec dirname {} \;)
pool=$(find -L /etc/opt/remi/ -name "$domain.conf" -exec dirname {} \;)
fi
if [ ! -e "$pool" ]; then
check_result "$E_NOTEXIST" "php-fpm pool doesn't exist"
fi

View File

@@ -32,27 +32,21 @@ if [ -z "$WEB_BACKEND" ]; then
fi
# Set file locations
if [ -f /etc/redhat-release ]; then
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
php_fpm=""
if [ "$LOCAL_PHP" == "yes" ]; then
php_fpm="/usr/lib/systemd/system/brepo-php-fpm$version.service"
else
php_fpm="/etc/init.d/php$version-fpm"
php_fpm="/usr/lib/systemd/system/php$version-php-fpm.service"
fi
# Verify php version format
if [ -f /etc/redhat-release ]; then
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
else
if [[ ! $version =~ ^[0-9].[0-9]+ ]]; then
echo "The PHP version format is invalid, it should look like [0-9].[0-9]."
echo "Example: 7.0, 7.4, 8.0"
exit "$E_INVALID"
fi
if [[ ! $version =~ ^[0-9][0-9]+ ]]; then
echo "The PHP version format is invalid, it should look like [0-9][0-9]."
echo "Example: 70, 74, 80"
exit "$E_INVALID"
fi
# Remove backend template
[ -f $HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl ] && rm -f $HESTIA/data/templates/web/php-fpm/PHP-${version/\./_}.tpl
@@ -70,38 +64,33 @@ check_hestia_demo_mode
# Action #
#----------------------------------------------------------#
mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl
php$version-fpm php$version-gd php$version-intl php$version-mysql
php$version-soap php$version-xml php$version-zip php$version-mbstring
php$version-json php$version-bz2 php$version-pspell php$version-imagick php$version-pgsql
php$version-imap php$version-ldap"
if [ -f /etc/redhat-release ]; then
# Packages in Remi repo have names with php$version-php- prefixes
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
fi
# Check is version is 7.1 or below to add mcrypt
if [ -f /etc/redhat-release ]; then
if [[ $(echo "$version 72" | awk '{print ($1 < $2)}') == 1 ]]; then
mph="$mph php$version-php-mcrypt"
fi
mph=""
if [ "$LOCAL_PHP" == "yes" ]; then
mph="brepo-php$version brepo-php$version-fpm"
else
if [[ $(echo "$version 7.2" | awk '{print ($1 < $2)}') == 1 ]]; then
mph="$mph php$version-mcrypt"
fi
mph="php$version-common php$version-mbstring php$version-bcmath php$version-cli php$version-curl
php$version-fpm php$version-gd php$version-intl php$version-mysql
php$version-soap php$version-xml php$version-zip php$version-mbstring
php$version-json php$version-bz2 php$version-pspell php$version-imagick php$version-pgsql
php$version-imap php$version-ldap"
# Packages in Remi repo have names with php$version-php- prefixes
mph="php$version-php-fpm php$version-php-cgi php$version-php-mysqlnd php$version-php-pgsql
php$version-php-pdo php$version-php-common php$version-php-pecl-imagick php$version-php-imap
php$version-php-ldap php$version-php-pecl-apcu php$version-php-pecl-zip php$version-php-cli
php$version-php-opcache php$version-php-xml php$version-php-gd php$version-php-intl
php$version-php-mbstring php$version-php-pspell php$version-php-readline"
# Check is version is 7.1 or below to add mcrypt
if [[ $(echo "$version 72" | awk '{print ($1 < $2)}') == 1 ]]; then
mph="$mph php$version-php-mcrypt"
fi
fi
# Purge php packages
if [ -f '/etc/redhat-release' ]; then
dnf remove -y $mph > /dev/null 2>&1 &
else
apt-get -y purge $mph > /dev/null 2>&1 &
fi
dnf remove -y $mph > /dev/null 2>&1 &
BACK_PID=$!
# Check if package removal is done, print a spinner
@@ -119,40 +108,36 @@ echo
# Check if installation was successfully
if [ -f "$php_fpm" ]; then
echo "ERROR: Uninstallation failed, please run the following command manually for debugging:"
if [ -f '/etc/redhat-release' ]; then
echo "dnf remove $mph"
else
echo "apt-get purge $mph"
fi
echo "dnf remove $mph"
exit 1
fi
# Cleanup php folder
if [ -f '/etc/redhat-release' ]; then
[[ -d /etc/opt/remi/php$version ]] && rm -rf "/etc/opt/remi/php$version"
if [ "$LOCAL_PHP" == "yes" ]; then
[[ -d /opt/brepo/php$version ]] && rm -rf "/opt/brepo/php$version"
else
[[ -d /etc/php/$version ]] && rm -rf "/etc/php/$version"
[[ -d /etc/opt/remi/php$version ]] && rm -rf "/etc/opt/remi/php$version"
fi
if [ -f '/etc/redhat-release' ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
if [ "$WEB_BACKEND" = "php-fpm" ]; then
conf=$(find /opt/brepo/php* -name www.conf)
# Check if www.conf exists
if [ -z "$conf" ]; then
# If not grab the "last php version
last=$($BIN/v-list-sys-php "shell" | tail -n1)
cp -f $HESTIA/install/rpm/php-fpm/www.conf /opt/brepo/php$last/etc/php-fpm.d/www.conf
$BIN/v-restart-web-backend
fi
fi
else
if [ "$WEB_BACKEND" = "php-fpm" ]; then
conf=$(find /etc/opt/remi/php* -name www.conf)
# Check if www.conf exists
if [ -z "$conf" ]; then
# If not grab the "last php version
last=$($BIN/v-list-sys-php "shell" | tail -n1)
cp -f $HESTIA/install/rpm/php-fpm/www.conf /etc/opt/remi/php$version/php-fpm.d/www.conf
$BIN/v-restart-web-backend
fi
fi
else
if [ "$WEB_BACKEND" = "php-fpm" ]; then
conf=$(find /etc/php* -name www.conf)
# Check if www.conf exists
if [ -z "$conf" ]; then
# If not grab the "last php version
last=$($BIN/v-list-sys-php "shell" | tail -n1)
cp -f $HESTIA/install/deb/php-fpm/www.conf /etc/php/$last/fpm/pool.d/www.conf
cp -f $HESTIA/install/rpm/php-fpm/www.conf /etc/opt/remi/php$last/php-fpm.d/www.conf
$BIN/v-restart-web-backend
fi
fi

152
bin/v-ext-modules Executable file
View File

@@ -0,0 +1,152 @@
#!/opt/brepo/ruby33/bin/ruby
# info: action with extended modules
# options: COMMAND [COMMAND_OPTION | FORMAT] [FORMAT]
#
# example: v-ext-modules list json
#
# This function enables and disables additional modules
#----------------------------------------------------------#
# Variables & Functions #
#----------------------------------------------------------#
# Argument definition
v_command = ARGV[0]
v_ext_option = ARGV[1]
v_format = ARGV[2]
require "/usr/local/hestia/func_ruby/global_options"
load_ruby_options_defaults
$HESTIA = load_hestia_default_path_from_env
require "main"
require "modules"
hestia_check_privileged_user
load_global_bash_variables "/etc/hestiacp/hestia.conf"
if $HESTIA.nil?
hestia_print_error_message_to_cli "Can't find HESTIA base path"
exit 1
end
load_global_bash_variables "#{$HESTIA}/conf/hestia.conf"
#----------------------------------------------------------#
# Verifications #
#----------------------------------------------------------#
check_args 1, ARGV, "COMMAND [COMMAND_OPTION] [ACTION]"
# Perform verification if read-only mode is enabled
check_hestia_demo_mode
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
case v_command.to_sym
when :list, :state
info = []
pm = PluginManager.new
if v_command.to_sym == :state
if v_ext_option.nil?
hestia_print_error_message_to_cli "no module name specified"
log_event E_ARGS, $ARGUMENTS
exit 1
end
load_module = v_ext_option.to_s.strip.split(",")[0].to_s.strip
pm.load_plugins(nil, load_module)
else
pm.load_plugins
end
pm.get_loaded_plugins.each_key do |mod|
next if mod == "default"
inst = pm.get_instance(mod)
if inst.key != pm.get_key
hestia_print_error_message_to_cli "incorrect module with incorrect rights #{mod}"
log_event E_ARGS, $ARGUMENTS
exit 1
end
info_result = inst.info
info_result[:STATE] = hestia_ext_module_state_in_conf(info_result[:NAME], :get)
info << info_result
end
result_arr = info.sort do |a, b|
if a[:ID] < b[:ID]
-1
elsif a[:ID] > b[:ID]
1
else
a[:ID] < b[:ID]
end
end
if v_command.to_sym == :state
format = (v_format.nil? ? "shell" : v_format.strip)
else
format = (v_ext_option.nil? ? "shell" : v_ext_option.strip)
end
hestia_print_array_of_hashes(result_arr, format, "ID, NAME, DESCR, STATE, REQ, CONF")
when :enable
if v_ext_option.nil?
hestia_print_error_message_to_cli "no module name specified"
log_event E_ARGS, $ARGUMENTS
exit 1
end
pm = PluginManager.new
load_module = v_ext_option.to_s.strip.split(",")[0].to_s.strip
pm.load_plugins(nil, load_module)
if pm.get_loaded_plugins.key? load_module
if hestia_ext_module_state_in_conf(load_module, :get) == "disabled"
inst = pm.get_instance(load_module)
result = inst.enable()
if result == ""
hestia_ext_module_state_in_conf(load_module, :enable)
log_event OK, $ARGUMENTS
else
hestia_print_error_message_to_cli "module #{load_module} return error #{result}"
log_event E_MODULE, $ARGUMENTS
exit 1
end
end
else
hestia_print_error_message_to_cli "no module with name #{load_module} found"
log_event E_INVALID, $ARGUMENTS
exit 1
end
when :disable
if v_ext_option.nil?
hestia_print_error_message_to_cli "no module name specified"
log_event E_ARGS, $ARGUMENTS
exit 1
end
pm = PluginManager.new
load_module = v_ext_option.to_s.strip.split(",")[0].to_s.strip
pm.load_plugins(nil, load_module)
if pm.get_loaded_plugins.key? load_module
if hestia_ext_module_state_in_conf(load_module, :get) == "enabled"
inst = pm.get_instance(load_module)
result = inst.disable()
if result == ""
hestia_ext_module_state_in_conf(load_module, :disable)
log_event OK, $ARGUMENTS
else
hestia_print_error_message_to_cli "module #{load_module} return error #{result}"
log_event E_MODULE, $ARGUMENTS
exit 1
end
end
else
hestia_print_error_message_to_cli "no module with name #{load_module} found"
log_event E_INVALID, $ARGUMENTS
exit 1
end
else
hestia_print_error_message_to_cli "unknown command"
log_event E_INVALID, $ARGUMENTS
exit 1
end
exit 0

82
bin/v-ext-modules-run Executable file
View File

@@ -0,0 +1,82 @@
#!/opt/brepo/ruby33/bin/ruby
# info: action with extended modules
# options: MODULE_ID [MODULE_RELATED_COMMNDS]
#
# example: v-ext-modules passenger_manager list json
#
# This function enables and disables additional modules
#----------------------------------------------------------#
# Variables & Functions #
#----------------------------------------------------------#
# Argument definition
v_id = ARGV[0]
require "/usr/local/hestia/func_ruby/global_options"
load_ruby_options_defaults
$HESTIA = load_hestia_default_path_from_env
require "main"
require "modules"
hestia_check_privileged_user
load_global_bash_variables "/etc/hestiacp/hestia.conf"
if $HESTIA.nil?
hestia_print_error_message_to_cli "Can't find HESTIA base path"
exit 1
end
load_global_bash_variables "#{$HESTIA}/conf/hestia.conf"
#----------------------------------------------------------#
# Verifications #
#----------------------------------------------------------#
check_args 1, ARGV, "MODULE_ID [MODULE_RELATED_COMMNDS]"
# Perform verification if read-only mode is enabled
check_hestia_demo_mode
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
if v_id.nil?
hestia_print_error_message_to_cli "no module name specified"
log_event E_ARGS, $ARGUMENTS
exit 1
end
pm = PluginManager.new
load_module = v_id.strip
pm.load_plugins(nil, load_module)
if pm.get_loaded_plugins.key? load_module
if hestia_ext_module_state_in_conf(load_module, :get) == "enabled"
inst = pm.get_instance(load_module)
NEW_ARGV = if ARGV.length > 0
ARGV.drop(1)
else
ARGV
end
result = inst.command(NEW_ARGV)
if result == ""
log_event OK, $ARGUMENTS
else
hestia_print_error_message_to_cli "module #{load_module} return error #{result}"
log_event E_MODULE, $ARGUMENTS
exit 1
end
else
hestia_print_error_message_to_cli "module #{load_module} disabled"
log_event E_INVALID, $ARGUMENTS
exit 1
end
else
hestia_print_error_message_to_cli "no module with name #{load_module} found"
log_event E_INVALID, $ARGUMENTS
exit 1
end
exit 0

View File

@@ -36,7 +36,8 @@ json_list() {
"METHOD": "'$method'",
"SALT": "'$salt'",
"TIME": "'$time'",
"DATE": "'$date'"
"DATE": "'$date'",
"ROUND":"'$round'"
}'
echo '}'
}
@@ -45,17 +46,18 @@ json_list() {
shell_list() {
echo "METHOD: $method"
echo "SALT: $salt"
echo "ROUND: $round"
}
# PLAIN list function
plain_list() {
echo -e "$method\t$salt"
echo -e "$method\t$salt\t$round"
}
# CSV list function
csv_list() {
echo "METHOD,SALT"
echo "$method, $salt"
echo "METHOD,SALT,ROUND"
echo "$method, $salt, $round"
}
#----------------------------------------------------------#
@@ -81,6 +83,11 @@ shadow=$(grep "^$user:" /etc/shadow | cut -f 2 -d :)
if echo "$shadow" | grep -qE '^\$[0-9a-z]+\$[^\$]+\$'; then
salt=$(echo "$shadow" | cut -f 3 -d \$)
round=""
if [[ "$salt" =~ ^rounds= ]]; then
round=$salt
salt=$(echo "$shadow" | cut -f 4 -d \$)
fi
method=$(echo "$shadow" | cut -f 2 -d \$)
if [ "$method" = "y" ]; then
method='yescrypt'

View File

@@ -67,14 +67,14 @@ csv_list() {
declare -a versions
# List through /etc/php
if [ -f /etc/redhat-release ]; then
for version in /etc/opt/remi/php*/php-fpm.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
if [ "$LOCAL_PHP" == "yes" ]; then
for version in /opt/brepo/php*/etc/php-fpm.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
versions+=("$ver")
done
else
for version in /etc/php/*/fpm/pool.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }')
for version in /etc/opt/remi/php*/php-fpm.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
versions+=("$ver")
done
fi

View File

@@ -69,8 +69,8 @@ HOSTNAME=$(hostname)
# Check OS/Release
if [ -d '/etc/sysconfig' ]; then
if [ -e '/etc/redhat-release' ]; then
OS='CentOS'
VERSION=$(cat /etc/redhat-release | tr ' ' '\n' | grep [0-9])
OS=$(cat /etc/redhat-release | cut -d' ' -f1)
VERSION=$(cat /etc/redhat-release | tr ' ' '\n' | grep -P "\d+(\.\d+)?")
else
OS="Amazon"
VERSION=$(cat /etc/issue | tr ' ' '\n' | grep [0-9])

View File

@@ -67,21 +67,29 @@ csv_list() {
declare -a versions
# List through /etc/php
if [ -f /etc/redhat-release ]; then
for version in /etc/opt/remi/php*/; do
ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed 's|php||')
versions+=("$ver")
done
else
if [ -n "$WEB_BACKEND" ]; then
for version in /etc/php/*/fpm; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }')
if [ "$LOCAL_PHP" == "yes" ]; then
if [ -n "$WEB_BACKEND" ]; then
for version in /opt/brepo/php*/; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed 's|php||')
versions+=("$ver")
done
else
# Fix for modphp
for version in /etc/php/*/cli; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }')
for version in /opt/brepo/php*/bin/php; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed 's|php||')
versions+=("$ver")
done
fi
else
if [ -n "$WEB_BACKEND" ]; then
for version in /etc/opt/remi/php*/; do
ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed 's|php||')
versions+=("$ver")
done
else
# Fix for modphp
for version in /opt/remi/php*/root/bin/php; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed 's|php||')
versions+=("$ver")
done
fi

View File

@@ -1,6 +1,6 @@
#!/bin/bash
# info: list php config parameters
# options: [FORMAT]
# options: [VERSION] [FORMAT]
#
# example: v-list-sys-php-config
#
@@ -11,7 +11,8 @@
#----------------------------------------------------------#
# Argument definition
format=${1-shell}
php_ver=${1-default}
format=${2-shell}
# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
@@ -61,24 +62,53 @@ csv_list() {
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
declare -a versions
if [ "$php_ver" == "default" ]; then
# List through /etc/php
if [ "$LOCAL_PHP" == "yes" ]; then
for version in /opt/brepo/php*/etc/php-fpm.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
if [ "$ver" != "php*" ]; then
versions+=("$ver")
fi
done
else
for version in /etc/opt/remi/php*/php-fpm.d/www.conf; do
ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
if [ "$ver" != "php*" ]; then
versions+=("$ver")
fi
done
fi
else
ver=$(echo "$php_ver" | sed "s/php\([[:digit:]]\+\)/\1/g")
versions+=("$ver")
fi
if [ ${#versions[@]} -eq 0 ]; then
php_ver="82"
else
php_ver="${versions[0]}"
fi
# Defining config path
if [ -f /etc/redhat-release ]; then
config_path=$(find /etc/opt/remi/php* -name php.ini)
if [ "$LOCAL_PHP" == "yes" ]; then
config_path=$(find /opt/brepo/php${php_ver}/* -name php.ini)
else
config_path=$(find /etc/php* -name php.ini)
config_path=$(find /etc/opt/remi/php${php_ver}/* -name php.ini)
fi
config_count=$(echo "$config_path" | wc -l)
if [ "$config_count" -gt 1 ]; then
if [ -f /etc/redhat-release ]; then
multiphp_versions=$(ls -d /etc/opt/remi/php*/php-fpm.d 2> /dev/null | wc -l)
if [ "$LOCAL_PHP" == "yes" ]; then
multiphp_versions=$(ls -d /opt/brepo/php*/etc/php-fpm.d 2> /dev/null | wc -l)
else
multiphp_versions=$(ls -d /etc/php/*/fpm/pool.d 2> /dev/null | wc -l)
multiphp_versions=$(ls -d /etc/opt/remi/php*/php-fpm.d 2> /dev/null | wc -l)
fi
if [ "$WEB_BACKEND" = 'php-fpm' ] || [ "$multiphp_versions" -gt 0 ]; then
config_path=$(echo "$config_path" | grep fpm)
config_path=$(echo "$config_path" | grep "php")
else
config_path=$(echo "$config_path" | grep apache)
config_path=$(echo "$config_path" | grep httpd)
fi
fi
@@ -88,7 +118,7 @@ keys="$keys |upload_max_filesize |post_max_size"
keys="$keys |display_errors |error_reporting "
# Reading config
config=$(cat $config_path | grep -v "^;")
config=$(cat "$config_path" | grep -v "^;")
# Listing data
case $format in

View File

@@ -86,7 +86,7 @@ get_srv_state() {
rtime="0"
# Searching related pids
if [ -f /etc/redhat-release ] && [ "$name" = "php-fpm" ]; then
if [ "$name" = "php-fpm" ]; then
pids=''
for php_pid in $(pidof php-fpm); do
process_info=$(ps -p "$php_pid" -o args | tail -n1 | grep "$srv")
@@ -174,7 +174,16 @@ fi
# Checking PHP intepreter
if [ -n "$WEB_BACKEND" ] && [ "$WEB_BACKEND" != 'remote' ]; then
if [ -f /etc/redhat-release ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
php_versions=$(ls /opt/brepo/php*/sbin/php-fpm | cut -d'/' -f4 | sed 's|php||')
for version in $php_versions; do
proc_name="php-fpm"
service_name="fpm${version}"
get_srv_state "$proc_name"
data="$data\nNAME='brepo-php-$service_name' SYSTEM='php interpreter' STATE='$state'"
data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'"
done
else
php_versions=$(ls /opt/remi/php*/root/sbin/php-fpm | cut -d'/' -f4 | sed 's|php||')
for version in $php_versions; do
proc_name="php-fpm"
@@ -183,15 +192,6 @@ if [ -n "$WEB_BACKEND" ] && [ "$WEB_BACKEND" != 'remote' ]; then
data="$data\nNAME='$service_name-php-fpm' SYSTEM='php interpreter' STATE='$state'"
data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'"
done
else
php_versions=$(ls /usr/sbin/php*fpm* | cut -d'/' -f4 | sed 's|php-fpm||')
for version in $php_versions; do
proc_name="php-fpm${version}"
service_name="php${version}-fpm"
get_srv_state "$service_name" "$proc_name"
data="$data\nNAME='$service_name' SYSTEM='php interpreter' STATE='$state'"
data="$data CPU='$cpu' MEM='$mem' RTIME='$rtime'"
done
fi
fi

View File

@@ -32,6 +32,10 @@ is_format_valid 'service' 'restart'
# Action #
#----------------------------------------------------------#
if [ "$service" == "apache2" ]; then
service="httpd"
fi
log="/dev/null"
if [ "$DEBUG_MODE" = "true" ]; then
@@ -49,13 +53,21 @@ if [ "$service" = "php-fpm" ]; then
php_versions=$($BIN/v-list-sys-php plain)
# Substitute php-fpm service name formats
for version in $php_versions; do
service_list="${service_list} php${version}-fpm"
if [ "$LOCAL_PHP" == "yes" ]; then
service_list="${service_list} brepo-php-fpm${version}"
else
service_list="${service_list} php${version}-php-fpm"
fi
done
else
service_list="$service"
fi
for service in $service_list; do
is_fpm="no"
if [[ "$service" =~ ^php[0-9.]+-php-fpm ]] || [[ "$service" =~ brepo-php-fpm[0-9.]+ ]]; then
is_fpm="yes"
fi
if [ "$service" = "iptables" ]; then
# Run the restart rules for iptables firewall
$BIN/v-stop-firewall
@@ -64,21 +76,13 @@ for service in $service_list; do
service $service upgrade >> $log 2>&1
elif [ -z "$restart" -o "$restart" = "no" ] && [ \
"$service" = "nginx" -o \
"$service" = "apache2" -o \
"$service" = "httpd" -o \
"$service" = "exim4" -o \
"$service" = "dovecot" -o \
"$service" = "bind9" -o \
"$service" = "named" -o \
"$service" = "vsftpd" -o \
"$service" = "php5.6-fpm" -o \
"$service" = "php7.0-fpm" -o \
"$service" = "php7.1-fpm" -o \
"$service" = "php7.2-fpm" -o \
"$service" = "php7.3-fpm" -o \
"$service" = "php7.4-fpm" -o \
"$service" = "php8.0-fpm" -o \
"$service" = "php8.1-fpm" -o \
"$service" = "php8.2-fpm" -o \
"$is_fpm" = "yes" -o \
"$service" = "proftpd" -o \
"$service" = "ssh" -o \
"$service" = "fail2ban" ]; then

View File

@@ -58,21 +58,21 @@ tmpfile=$(mktemp)
if [ -z "$version" ]; then
# Substitute php-fpm service name formats
for version in $($BIN/v-list-sys-php plain); do
if [ -f /etc/redhat-release ]; then
v_php="php$version-php-fpm"
if [ "$LOCAL_PHP" == "yes" ]; then
v_php="brepo-php-fpm$version"
else
v_php="php$version-fpm"
v_php="php$version-php-fpm"
fi
if [ -f /etc/redhat-release ]; then
if [ "$LOCAL_PHP" == "yes" ]; then
if [ ! -f "/opt/brepo/php${version}/etc/php-fpm.d/dummy.conf" ]; then
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /opt/brepo/php${version}/etc/php-fpm.d/
sed -i "s/9999/99$v_tpl/g" /opt/brepo/php${version}/etc/php-fpm.d/dummy.conf
fi
else
if [ ! -f "/etc/opt/remi/php${version}/php-fpm.d/dummy.conf" ]; then
cp -f $HESTIA_INSTALL_DIR/php-fpm/dummy.conf /etc/opt/remi/php${version}/php-fpm.d/
sed -i "s/9999/99$v_tpl/g" /etc/opt/remi/php${version}/php-fpm.d/dummy.conf
fi
else
if [ ! -f "/etc/php/${version}/fpm/pool.d/dummy.conf" ]; then
cp -f "$HESTIA_INSTALL_DIR/php-fpm/dummy.conf" "/etc/php/${version}/fpm/pool.d/"
sed -i "s/9999/99${version//./}/g" "/etc/php/${version}/fpm/pool.d/dummy.conf"
fi
fi
$BIN/v-restart-service "$v_php" "$restart"
@@ -82,10 +82,10 @@ if [ -z "$version" ]; then
fi
done
else
if [ -f /etc/redhat-release ]; then
v_php="php$version-php-fpm"
if [ "$LOCAL_PHP" == "yes" ]; then
v_php="brepo-php-fpm$version"
else
v_php="php$version-fpm"
v_php="php$version-php-fpm"
fi
$BIN/v-restart-service "$v_php" "$restart"
if [ $? -ne 0 ]; then

View File

@@ -43,6 +43,15 @@ if [ "$clicmd" = "wp" ]; then
clicmd="$homedir/.wp-cli/wp"
fi
if [[ "$clicmd" =~ php[0-9][0-9] ]]; then
php_ver=$(echo "$clicmd" | grep -oP "\d+")
if [ "$LOCAL_PHP" == "yes" ]; then
clicmd="/opt/brepo/php${php_ver}/bin/php"
else
clicmd="/usr/bin/php${php_ver}"
fi
fi
if [ -z "$(which "$clicmd")" ]; then
check_result "$E_NOTEXIST" "Cli command does not exist $clicmd"
fi
@@ -61,15 +70,6 @@ if [ "$basecmd" != 'ps' -a \
"$basecmd" != 'egrep' -a \
"$basecmd" != 'sed' -a \
"$basecmd" != 'cat' -a \
"$basecmd" != 'php5.6' -a \
"$basecmd" != 'php7.0' -a \
"$basecmd" != 'php7.1' -a \
"$basecmd" != 'php7.2' -a \
"$basecmd" != 'php7.3' -a \
"$basecmd" != 'php7.4' -a \
"$basecmd" != 'php8.0' -a \
"$basecmd" != 'php8.1' -a \
"$basecmd" != 'php8.2' -a \
"$basecmd" != 'php' -a \
"$basecmd" != "wp" -a \
"$basecmd" != 'composer' ]; then

84
bin/v-update-web-domain Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/bash
# info: update configs for web domain
# options: USER DOMAIN TEMPLATE [RESTART]
#
# example: v-unpdate-web-domain admin acme.com test_template
#
# This function of updating of the domain's configs and set template or notemplate if just update of configs
#----------------------------------------------------------#
# Variables & Functions #
#----------------------------------------------------------#
# Argument definition
user=$1
domain=$2
domain_idn=$2
template=$3
restart=$4
# Includes
# shellcheck source=/etc/hestiacp/hestia.conf
source /etc/hestiacp/hestia.conf
# shellcheck source=/usr/local/hestia/func/main.sh
source $HESTIA/func/main.sh
# shellcheck source=/usr/local/hestia/func/domain.sh
source $HESTIA/func/domain.sh
# shellcheck source=/usr/local/hestia/func/ip.sh
source $HESTIA/func/ip.sh
# load config file
source_conf "$HESTIA/conf/hestia.conf"
# Additional argument formatting
format_domain
format_domain_idn
# TODO: $domain_idn not used in this script - maybe $domain should be converted to $doman_idn ?
#----------------------------------------------------------#
# Verifications #
#----------------------------------------------------------#
check_args '3' "$#" 'USER DOMAIN TEMPLATE [RESTART]'
is_format_valid 'user' 'domain'
is_system_enabled "$WEB_SYSTEM" 'WEB_SYSTEM'
is_object_valid 'user' 'USER' "$user"
is_object_valid 'web' 'DOMAIN' "$domain"
# Perform verification if read-only mode is enabled
check_hestia_demo_mode
#----------------------------------------------------------#
# Action #
#----------------------------------------------------------#
# Parsing domain values
get_domain_values 'web'
local_ip=$(get_real_ip $IP)
# Preparing domain values for the template substitution
prepare_web_domain_values
if [ "$template" != "notemplate" ]; then
update_object_value 'web' 'DOMAIN' "$domain" '$PROXY' "$template"
$BIN/v-log-action "system" "Info" "Web" "Set new template=$template for $PROXY (User: $user, Domain: $domain)."
fi
#----------------------------------------------------------#
# Hestia #
#----------------------------------------------------------#
# Update global configuration files
$BIN/v-rebuild-web-domain "$user" "$domain" 'no'
# Restarting web server
$BIN/v-restart-web "$restart"
check_result $? "Web restart failed" > /dev/null
$BIN/v-restart-proxy "$restart"
check_result $? "Proxy restart failed" > /dev/null
# Logging
$BIN/v-log-action "system" "Info" "Web" "Updated web domain (User: $user, Domain: $domain)."
log_event "$OK" "$ARGUMENTS"
exit

View File

@@ -50,11 +50,22 @@ for webtpl_folder in $(ls $HESTIA_INSTALL_DIR/templates/web/* -d 2> /dev/null |
cp -rf "${webtpl_folder}" "${WEBTPL}/"
done
versions_list=$(ls -d /etc/php/*)
for php_ver in $versions_list; do
[ ! -d "/etc/php/$php_ver/fpm/pool.d/" ] && continue
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl ${WEBTPL}/php-fpm/PHP-${php_ver/\./_}.tpl
done
versions_list=""
if [ "$LOCAL_PHP" == "yes" ]; then
versions_list=$(ls -d /opt/brepo/php*)
for php_ver in $versions_list; do
[ ! -d "$php_ver/etc/php-fpm.d" ] && continue
vers=$(echo "$php_ver" | awk -F"/" '{ print $4 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl ${WEBTPL}/php-fpm/PHP-${vers/\./_}.tpl
done
else
versions_list=$(ls -d /etc/opt/remi/php*)
for php_ver in $versions_list; do
[ ! -d "$php_ver/php-fpm.d" ] && continue
vers=$(echo "$php_ver" | awk -F"/" '{ print $5 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
cp -f $HESTIA_INSTALL_DIR/php-fpm/multiphp.tpl ${WEBTPL}/php-fpm/PHP-${vers/\./_}.tpl
done
fi
if [ -n "$awstats_patch" ]; then
# restore LoadPlugin variable

View File

@@ -24,7 +24,7 @@ export default defineConfig({
socialLinks: [
{ icon: 'github', link: 'https://dev.brepo.ru/bayrepo/hestiacp' },
{ icon: 'github', link: 'https://github.com/bayrepo/hestiacp' },
{ icon: 'github', link: 'https://github.com/bayrepo/hestiacp-rpm' },
{ icon: 'github', link: 'https://github.com/hestiacp/hestiacp' },
],
@@ -150,6 +150,8 @@ function sidebarDocs() {
collapsed: false,
items: [
{ text: 'PHP cli селектор', link: '/docs/extensions/php-cli-selector.md' },
{ text: 'Расширенные модули', link: '/docs/extensions/extended-modules.md' },
{ text: 'Настройка Local PHP', link: '/docs/extensions/local-php.md' },
],
},
];

View File

@@ -0,0 +1,151 @@
# Расширенные модули
## Что такое модули
Модули расширения панели позволяют расширять функционал панели.
## Как управлять модулями
Для доступа к модулям расширения необходимо из-под пользователя `admin` перейти в `Настройки сервера`:
![ext_modules_step1](/images/ext_modules_step1.png)
Далее в строке выбора настроек выбрать `Доп. модули`:
![ext_modules_step2](/images/ext_modules_step2.png)
Далее откроется страинца достпных модулей и их сотояния.
Пример страницы с демонстрационными модулями приведен ниже:
![ext_modules_step3](/images/ext_modules_step3.png)
Данная страница содержит следующую информацию:
- **ID модуля** - числовой идентификатор модуля
- **Имя модуля** - сивольный идентификатор модуля
- **Описание модуля** - краткая ифнормация о модуле
- **Состояние** - включен(enabled) или выключен(disabled)
- **Зависимости** - список модулей, которые должны быть включены для работы текущего модуля
- **Конфигурация** - дополнительные настройки модуля (при наличии)
Если модуль выключен, его состояние отображается как disabled.
Для включения модуля необходимо нажать на кнопку <i class="fas fa-play"></i>, для выключения модуля необходимо нажать на кнопку <i class="fas fa-stop"></i>.
## Список предустановленных модулей
- **puppet_installer** - установить puppet, для большинства модулей требуется puppet для изменения конфигурации системы, поэтому требуется, чтоб этот модуль был включен, при включении он установит puppet в систему.
- **empty_module** - пустой модуль, его включение или выключение не начто не влияет, является примером написания модулей
- **passenger_manager** - модуль по установке и настройке passenger в систему.
- **php_brepo_modules** - модуль по управлению расширениями Local PHP. [Описание интерфейса](/docs/extensions/local-php.md)
## Управление модулями из командной строки
Для управления модулями используется утилита `v-ext-modules`.
Доступные команды:
- **list** - вывести список доступных модулей
- **enable module_name** - включить модуль
- **disable module_name** - выключить модуль
- **state module_name** - состояние модуля
Примеры:
```
# v-ext-modules list csv
1,puppet_installer,"Added puppet support, needed for another modules","","",enabled
2,passenger_manager,Added passenger support for nginx,puppet_installer,yes,enabled
3,empty_module,Just empty module for storing max module id,"","",disabled
```
```
# v-ext-modules state passenger_manager
ID NAME DESCR STATE REQ CONF
-- ---- ----- ----- --- ----
2 passenger_manager Added passenger support for nginx enabled puppet_installer yes
```
## passenger_manager
Модуль, для добавления поддержки passenger+nginx для запуска (пока что только) ruby приложений.
### passenger_manager настройка
Для настройки модуля нажмите на ссылку `Изменить`:
![ext_modules_step4](/images/ext_modules_step4.png)
Откроется страница вида:
![ext_modules_step5](/images/ext_modules_step5.png)
- **Добавить новый путь ruby** - добавить путь к бинарному файлу интерпретатору ruby, если его еще нет в списке ниже
- **Ruby list** - список достпных для выбора ruby интерпретаторов. Для удаления ruby из списка необходимо нажать на значек <i class="fas fa-trash-can"></i>.
При активации `passenger_manager` в меню настройки домена для пользователя появляется кнопка `Настройки passenger`:
![ext_modules_step6](/images/ext_modules_step6.png)
При нажатии на которую открывается форма:
![ext_modules_step7](/images/ext_modules_step7.png)
Где можно активировать passenger для домена установкой галочки `Включить passenger для домена`, а так же выбрать из списка ruby.
Галочка `Включить логирование в браузер`, активирует вывод лога ошибки приложения в браузер, рекомендуется ее включать только при настройке приложения.
Пример установки приложения:
пусть есть пользователь `test2` и домен `ttt142.my.brp`, для него активируется passenger.
Для него генерируются следующие настройки:
```
location / {
passenger_base_uri /;
passenger_app_root /home/test2/web/ttt142.my.brp/private;
passenger_document_root /home/test2/web/ttt142.my.brp/public_html;
passenger_startup_file config.rb;
passenger_app_type rack;
}
```
В `config.rb` необходимо поместить инструкции запуска приложения:
```
# encoding: UTF-8
require './test'
run Sinatra::Application
```
и соновное приложение разметсить в каталоге `/home/test2/web/ttt142.my.brp/private`.
Остальная логика будет размещена в `test.rb`, для примера вот так:
```
!/usr/bin/env ruby
require 'sinatra'
get '/' do
"Hello #{Process.uid}"
end
```
Статические файлы располагать в каталоге `/home/test2/web/ttt142.my.brp/public_html`, а так же из этого каталога удалить файл `index.html` создаваемый как заглушка для пустого сайта.
Так же создать файл `Gemfile` в каталоге `/home/test2/web/ttt142.my.brp/private` и выполнить от пользователя:
```
bundle config set --local path 'vendor'
bundle install
```
или по старому:
```
bundle install --path=vendor
```
для установки пользователю необходимых гемов локально.

View File

@@ -0,0 +1,35 @@
# Local PHP
PHP интерпретатор из репозитория, из которого ставится HestiaCP RPM Edition.
HestiaCP RPM Edition имеет возможность работать или с PHP из Remi репозитория или с PHP из т.н. локального репозитория - Local PHP.
Если требуется более расширенный функционал пакетов из Remi репозитория, то следует отказаться при установке панели от опции `uselocalphp yes` и установить панель с опцией `uselocalphp no`.
Local PHP более ограниченный в наборе расширений, но занимает меньше места на диске и приносит меньше RPM пакетов. Подходит для большинства сборок CMS таких как Wordpress, Drupal и т.д.
Есть еще одна особенность, для данного типа PHP разработан графический интерфейс по управлению подключенными расширениями.
## Графический интерфейс управления расширениями PHP
Для включения графического интерфейса необходимо перейти в настройки панели под администратором и выбрать закладку "Дополнительные модули".
![ext_modules_step2](/images/ext_modules_step2.png)
На окрывшейся веб странице необходимо активировать модуль **php_brepo_modules**.
![local_php_step1](/images/local_php_1.png)
Справа от названия модуля появится пункт меню - `Изменить`.
При нажатии мышкой на ссылку `Изменить`, откроется окно выбора версии PHP, для которой требуется перенастройка расширений.
![local_php_step2](/images/local_php_2.png)
Здесь будут отображаться все установленные на сервере версии Local PHP. Для настройки модулей необходимо нажать мышкой на шестеренке справа от версии PHP (<i class="fa-solid fa-gear icon-purple"></i>), в пункте меню `Изменить список модулей` <i class="fa-solid fa-gear icon-purple"></i>.
Откроется страница выбора расширений.
![local_php_step3](/images/local_php_3.png)
Здесь приведен список установленных расширений. Галочками подсвечены активные расширения.
Здесь можно убрать галочки напротив названия модуля или наоборот установить галочку. И нажать `Сохранить` для изменения конфигурации расширений для выбранной версии PHP или `Назад`, для отмены изменений.

View File

@@ -58,5 +58,6 @@
## Дополнения
- [PHP cli селектор](/docs/extensions/php-cli-selector.md')
- [PHP cli селектор](/docs/extensions/php-cli-selector.md)
- [Расширенные модули](/docs/extensions/extended-modules.md)
- [Настройка Local PHP](/docs/extensions/local-php.md)

View File

@@ -101,6 +101,7 @@ bash hst-install.sh -h
-l, --lang Default language default: en
-y, --interactive Interactive install [yes|no] default: yes
-I, --nopublicip Use local ip [yes|no] default: yes
-u, --uselocalphp Use PHP from local repo [yes|no] default: yes
-s, --hostname Set hostname
-e, --email Set admin email
-p, --password Set admin password
@@ -118,14 +119,14 @@ bash hst-install.sh \
--hostname host.domain.tld \
--email email@domain.tld \
--password p4ssw0rd \
--lang fr \
--lang ru \
--apache no \
--named no \
--clamav no \
--spamassassin no
```
Эта команда установит Hestia на французском с такой конфигурацией:
Эта команда установит Hestia на русском с такой конфигурацией:
- Nginx веб сервер
- PHP-FPM сервер приложений
@@ -140,3 +141,11 @@ bash hst-install.sh \
К настоящему моменту у вас должна быть установлена Hestia на вашем сервере. Вы готовы добавлять новых пользователей, чтобы вы (или они) могли добавлять новые веб-сайты на вашем сервере.
Чтобы получить доступ к панели управления, перейдите по адресу `https://host.domain.tld:8083` или `http://your.public.ip.address:8083`
## Расширенные опции RPM версии
Данная реадкция HestiaCP RPM Edition включает дополнительные оции такие как:
- `-I, --nopublicip` - если установлена данная опция, то установщик панели не получает внешний IP адрес сервера, где контрольная панель устанавливается (на случай если ваш сервер за NAT). Данную опцию можно включать, если у вас на сервере публичный IP или необходима внутрисетевая установка без внешнего доступа.
- `-u, --uselocalphp` - включить установку пакетов PHP из того-же репозитория, откуда ставится HestiaCP RPM Edition. Если не включать данную опцию, то PHP пакеты будут установлены из репозитория Remi. Если включить, то будет произведена так называемая установка локальных пакетов. Есть отличия в способе упаковке Local PHP и Remi PHP. Если сервера требуется расширенный набор PHP из Remi репозитория, то данную опцию лучше отключить, т.е задать `--uselocalphp no`. Local PHP более простая сборка с меньшим числом поддерживаемых модулей PHP, но подходит для большинства конфигураций CMS и имеет [страницу настройки подключаемых модулей](/docs/extensions/local-php.md)

View File

@@ -83,13 +83,13 @@ cp original.sh new.sh
## Установка модулей PHP
```bash
apt install php-package-name
dnf install php-package-name
```
Например, следующая команда установит `php-memcached` и `php-redis`, включая необходимые дополнительные пакеты для PHP.
```bash
apt install php-memcached php-redis
dnf install php-memcached php-redis
```
## Nginx FastCGI Cache
@@ -102,12 +102,6 @@ FastCGI применяется только для сервера Nginx + PHP-FP
Кэш FastCGI лучше всего подходит для сайтов, получающих много запросов и страницы которых не так часто меняются, например, новостной сайт. Для более динамичных сайтов могут потребоваться изменения в конфигурации или полное его отключение.
### Почему программные пакеты x и y не работают с кэшем FastCGI
Поскольку у нас более 20 различных шаблонов, и мы не используем их все, мы решили прекратить выпуск новых в будущем и надеемся, что сообщество поможет улучшить шаблоны, [отправив запрос на извлечение](https://github.com/hestiacp/hestiacp/pulls).
Если вы хотите добавить поддержку определенного шаблона, следуйте инструкциям ниже.
### Как включить кэш FastCGI для моего пользовательского шаблона
Найдите блок, в котором вы вызываете `fastcgi_pass`:
@@ -153,7 +147,7 @@ v-purge-nginx-cache user domain.tld
Да, Hestia отлично работает с веб-сокетами, однако наши шаблоны по умолчанию включают по умолчанию:
```bash
proxy_hide_header Обновление
proxy_hide_header Upgrade
```
Это решило проблему с загрузкой веб-сайтов Safari.

View File

@@ -123,8 +123,12 @@
Здесь также будут отображаться любые пользовательские шаблоны.
- **srvproxy**: шаблон для конфигурации прокси для любого внутреннего сервиса, например gitea, который запускается и присоединеятся к порту или создает unix-сокет. При выборе данного шаблона, появляется дополнительное поле `Установить порт для локального сервиса`, в котором нужно указать путь к unix-сокету или порт внутреннего сервиса. В качестве шаблона Backend в данном случае можно выбрать `no-php`, т.к. в данном случае бакэндом будет сервис.
![domain_proxy](/images/proxy_domain.png)
::: tip
Любые пользовательские шаблоны, начинающиеся с `caching-`, позволят использовать кнопку **<i class="fas fa-fw fa-trash"></i> Очистить кэш Nginx**. Убедитесь, что файл `.sh` существует для `caching-my-template` с как минимум [этим содержимым](https://github.com/hestiacp/hestiacp/blob/main/install/deb/templates/web/nginx/caching.sh)
Любые пользовательские шаблоны, начинающиеся с `caching-`, позволят использовать кнопку **<i class="fas fa-fw fa-trash"></i> Очистить кэш Nginx**. Убедитесь, что файл `.sh` существует для `caching-my-template` с как минимум [этим содержимым](https://dev.brepo.ru/bayrepo/hestiacp/raw/branch/master/install/rpm/templates/web/nginx/caching.sh)
:::
### Веб-шаблоны

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -101,34 +101,33 @@ is_web_alias_new() {
prepare_web_backend() {
# Accept first function argument as backend template otherwise fallback to $template global variable
local backend_template=${1:-$template}
if [ -f "/etc/redhat-release" ]; then
pool=$(find -L /etc/opt/remi/php80/ -name "$domain.conf" -exec dirname {} \; 2>/dev/null)
php_type=$(cat "$HESTIA/conf/hestia.conf" | grep "LOCAL_PHP" | grep "yes")
if [ -n "$php_type" ]; then
pool=$(find -L /opt/brepo/ -name "$domain.conf" -exec dirname {} \; 2>/dev/null)
else
pool=$(find -L /etc/php/ -name "$domain.conf" -exec dirname {} \;)
pool=$(find -L /etc/opt/remi/php80/ -name "$domain.conf" -exec dirname {} \; 2>/dev/null)
fi
# Check if multiple-PHP installed
if [ -f "/etc/redhat-release" ]; then
regex="^.*PHP-([0-9])([0-9])$"
else
regex="^.*PHP-([0-9])\_([0-9])$"
fi
regex="^.*PHP-([0-9])([0-9])$"
if [[ $backend_template =~ $regex ]]; then
if [ -f "/etc/redhat-release" ]; then
if [ -n "$php_type" ]; then
backend_version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
pool=$(find -L /opt/brepo/php$backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
else
backend_version="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"
pool=$(find -L /etc/opt/remi/php$backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
else
backend_version="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}"
pool=$(find -L /etc/php/$backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
fi
else
backend_version=$(multiphp_default_version)
if [ -z "$pool" ] || [ -z "$BACKEND" ]; then
if [ -f "/etc/redhat-release" ]; then
if [ -n "$php_type" ]; then
m_backend_version="${backend_version//./}"
pool=$(find -L /opt/brepo/php$m_backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
else
m_backend_version="${backend_version//./}"
pool=$(find -L /etc/opt/remi/php$m_backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
else
pool=$(find -L /etc/php/$backend_version -type d \( -name "pool.d" -o -name "*fpm.d" \))
fi
fi
fi
@@ -151,11 +150,12 @@ prepare_web_backend() {
# Delete web backend
delete_web_backend() {
if [ -f "/etc/redhat-release" ]; then
find -L /etc/opt/remi/ -name "$backend_type.conf" -exec rm -f {} \;
else
find -L /etc/php/ -type f -name "$backend_type.conf" -exec rm -f {} \;
fi
php_type=$(cat "$HESTIA/conf/hestia.conf" | grep "LOCAL_PHP" | grep "yes")
if [ -n "$php_type" ]; then
find -L /opt/brepo/php* -name "$backend_type.conf" -exec rm -f {} \;
else
find -L /etc/opt/remi/ -name "$backend_type.conf" -exec rm -f {} \;
fi
}
# Prepare web aliases
@@ -193,6 +193,7 @@ prepare_web_domain_values() {
fi
group="$user"
docroot="$HOMEDIR/$user/web/$domain/public_html"
docrtpriv="$HOMEDIR/$user/web/$domain/private"
sdocroot="$docroot"
if [ "$SSL_HOME" = 'single' ]; then
sdocroot="$HOMEDIR/$user/web/$domain/public_shtml"
@@ -271,6 +272,7 @@ convert_proxy_ngix_internal_redirect(){
# Add web config
add_web_config() {
# Check if folder already exists
TPLNM="$2"
if [ "$1" = "httpd" ]; then
confd="conf.h.d"
else
@@ -281,8 +283,30 @@ add_web_config() {
mkdir -p "$HOMEDIR/$user/conf/web/$domain/"
fi
PASS_TPL=""
if [[ "$TPLNM" =~ ^passenger ]]; then
#Passenger generator
if [ -e /usr/local/hestia/bin/v-ext-modules ]; then
res=$(/usr/local/hestia/bin/v-ext-modules state passenger_manager csv | tail -n 1 | /usr/bin/xargs | cut -d"," -f6 )
if [ -n "$res" ]; then
enabled=$(echo "$res" | grep enabled)
if [ -n "$enabled" ]; then
RUBY_RES=$(/usr/local/hestia/bin/v-ext-modules-run passenger_manager get_user_ruby "$domain" csv | tail -n1 | /usr/bin/xargs | cut -d"," -f1)
RUBY_RES_LOG=$(/usr/local/hestia/bin/v-ext-modules-run passenger_manager get_user_ruby "$domain" csv | tail -n1 | /usr/bin/xargs | cut -d"," -f2)
if [ -n "$RUBY_RES" ]; then
pass_tpl_dir=$(/usr/local/hestia/bin/v-ext-modules-run passenger_manager get_tpl_path | tail -n1 | /usr/bin/xargs)
if [ -n "$pass_tpl_dir" ]; then
pass_tpl_dir=${pass_tpl_dir%/}
PASS_TPL="$pass_tpl_dir"
fi
fi
fi
fi
fi
fi
conf="$HOMEDIR/$user/conf/web/$domain/$1.conf"
if [[ "$2" =~ stpl$ ]]; then
if [[ "$TPLNM" =~ stpl$ ]]; then
conf="$HOMEDIR/$user/conf/web/$domain/$1.ssl.conf"
fi
@@ -291,17 +315,21 @@ add_web_config() {
WEBTPL_LOCATION="$WEBTPL/$1"
if [ "$1" != "$PROXY_SYSTEM" ] && [ -n "$WEB_BACKEND" ] && [ -d "$WEBTPL_LOCATION/$WEB_BACKEND" ]; then
if [ -f "$WEBTPL_LOCATION/$WEB_BACKEND/$2" ]; then
if [ -f "$WEBTPL_LOCATION/$WEB_BACKEND/$TPLNM" ]; then
# check for backend specific template
WEBTPL_LOCATION="$WEBTPL/$1/$WEB_BACKEND"
fi
fi
if [[ "$TPLNM" =~ ^passenger ]] && [ -n "$PASS_TPL" ]; then
WEBTPL_LOCATION="$PASS_TPL"
fi
# Note: Removing or renaming template variables will lead to broken custom templates.
# -If possible custom templates should be automatically upgraded to use the new format
# -Alternatively a depreciation period with proper notifications should be considered
cat "${WEBTPL_LOCATION}/$2" \
cat "${WEBTPL_LOCATION}/$TPLNM" \
| sed -e "s|%ip%|$local_ip|g" \
-e "s|%domain%|$domain|g" \
-e "s|%domain_idn%|$domain_idn|g" \
@@ -329,9 +357,10 @@ add_web_config() {
-e "s|%ssl_pem%|$ssl_pem|g" \
-e "s|%ssl_ca_str%|$ssl_ca_str|g" \
-e "s|%ssl_ca%|$ssl_ca|g" \
-e "s|%docrtpriv%|$docrtpriv|g" \
> $conf
if [ "$2" == "srvproxy.tpl" -o "$2" == "srvproxy.stpl" ];then
if [ "$TPLNM" == "srvproxy.tpl" -o "$TPLNM" == "srvproxy.stpl" ];then
proxy_backend_port_internal=$(convert_proxy_ngix_internal_redirect "$3")
cat "$conf" \
| sed -e "s|%proxy_backend_srv_port%|$proxy_backend_port_internal|g" \
@@ -339,12 +368,20 @@ add_web_config() {
mv -f ${conf}.tmp $conf
fi
if [[ "$TPLNM" =~ ^passenger ]] && [ -n "$PASS_TPL" ]; then
cat "$conf" \
| sed -e "s|%rubypath%|$RUBY_RES|g" \
-e "s|%rubylog%|$RUBY_RES_LOG|g" \
> $conf.tmp
mv -f ${conf}.tmp $conf
fi
process_http2_directive "$conf"
chown root:$user $conf
chmod 640 $conf
if [[ "$2" =~ stpl$ ]]; then
if [[ "$TPLNM" =~ stpl$ ]]; then
rm -f /etc/$1/$confd/domains/$domain.ssl.conf
ln -s $conf /etc/$1/$confd/domains/$domain.ssl.conf
@@ -382,7 +419,7 @@ add_web_config() {
done
fi
trigger="${2/.*pl/.sh}"
trigger="${TPLNM/.*pl/.sh}"
if [ -x "${WEBTPL_LOCATION}/$trigger" ]; then
$WEBTPL_LOCATION/$trigger \
$user $domain $local_ip $HOMEDIR \

View File

@@ -1449,6 +1449,56 @@ check_backup_conditions() {
done
}
fn_get_link_name(){
str_result=""
ext_name=$1
pattern=("01-ioncube.ini" "10-opcache.ini" "20-bcmath.ini" "20-bz2.ini" "20-calendar.ini" "20-ctype.ini" "20-curl.ini" "20-dba.ini" "20-dom.ini" "20-enchant.ini" "20-exif.ini" "20-ffi.ini" "20-fileinfo.ini" "20-ftp.ini" "20-gd.ini" "20-gettext.ini" "20-gmp.ini" "20-iconv.ini" "20-imap.ini" "20-intl.ini" "20-ldap.ini" "20-mbstring.ini" "20-mysqlnd.ini" "20-odbc.ini" "20-pdo.ini" "20-phar.ini" "20-posix.ini" "20-pspell.ini" "20-shmop.ini" "20-simplexml.ini" "20-sockets.ini" "20-sqlite3.ini" "20-sysvmsg.ini" "20-sysvsem.ini" "20-sysvshm.ini" "20-tokenizer.ini" "20-xml.ini" "20-xmlwriter.ini" "20-xsl.ini" "30-mysqli.ini" "30-pdo_dblib.ini" "30-pdo_firebird.ini" "30-pdo_mysql.ini" "30-pdo_odbc.ini" "30-pdo_sqlite.ini" "30-xmlreader.ini" "30-zip.ini" "40-apcu.ini" "40-ast.ini" "40-bolt.ini" "40-brotli.ini" "40-geos.ini" "40-imagick.ini" "40-libvirt-php.ini" "40-lz4.ini" "40-pdlib.ini")
check="^[0-9]+-${ext_name}.ini"
for str in ${pattern[@]}; do
if [[ $str =~ $check ]]; then
str_result="$str"
break
fi
done
if [ -z "$str_result" ]; then
echo "50-${ext_name}.ini"
else
echo "$str_result"
fi
}
fn_enable_local_php_extension(){
vers=$1
ext_name=$2
ext_nm=$(fn_get_link_name "$ext_name")
if [ -e "/opt/brepo/php${vers}/etc/php.d/" ]; then
if [ ! -e "/opt/brepo/php${vers}/etc/php.d/${ext_nm}" -a -e "/opt/brepo/php${vers}/etc/mod-installed/${ext_name}.ini" ]; then
pushd "/opt/brepo/php${vers}/etc/php.d/"
ln -s ../mod-installed/${ext_name}.ini /opt/brepo/php${vers}/etc/php.d/${ext_nm}
popd
fi
fi
}
fn_disable_local_php_extension(){
vers=$1
ext_name=$2
ext_nm=$(fn_get_link_name "$ext_name")
if [ -e "/opt/brepo/php${vers}/etc/php.d/" ]; then
if [ -e "/opt/brepo/php${vers}/etc/php.d/${ext_nm}" ]; then
rm -f "/opt/brepo/php${vers}/etc/php.d/${ext_nm}"
fi
fi
}
fn_enable_mod_php(){
vers=$1
if [ -e "/etc/httpd/conf.d.prep/php${vers}.conf" ]; then
ln -s /etc/httpd/conf.d.prep/php${vers}.conf /etc/httpd/conf.h.d/mod_php${vers}.conf
fi
}
# Define download function
download_file() {
local url=$1
@@ -1511,9 +1561,16 @@ multiphp_count() {
multiphp_versions() {
local -a php_versions_list
local php_ver
local php_type_internal=$(cat "$HESTIA/conf/hestia.conf" | grep "LOCAL_PHP" | grep "yes")
local pool_internal=""
if [ "$(multiphp_count)" -gt 0 ]; then
for php_ver in $($BIN/v-list-sys-php plain); do
[ ! -d "/etc/php/$php_ver/fpm/pool.d/" ] && continue
if [ -n "$php_type_internal" ]; then
pool_internal="/opt/brepo/php$php_ver/etc/php-fpm.d"
else
pool_internal="/etc/opt/remi/php$php_ver/php-fpm.d"
fi
[ ! -d "$pool_internal" ] && continue
php_versions_list+=($php_ver)
done
echo "${php_versions_list[@]}"
@@ -1522,11 +1579,19 @@ multiphp_versions() {
multiphp_default_version() {
# Get system wide default php version (set by update-alternatives)
local sys_phpversion=$(php -r "echo substr(phpversion(),0,3);")
local sys_phpversion_l=$(php -r "echo substr(phpversion(),0,3);")
local sys_phpversion="${sys_phpversion_l//./}"
local php_type_internal=$(cat "$HESTIA/conf/hestia.conf" | grep "LOCAL_PHP" | grep "yes")
local pool_internal=""
if [ -n "$php_type_internal" ]; then
pool_internal="/opt/brepo/php$sys_phpversion/etc/php-fpm.d"
else
pool_internal="/etc/opt/remi/php$sys_phpversion/php-fpm.d"
fi
# Check if the system php also has php-fpm enabled, otherwise return
# the most recent php version which does have it installed.
if [ ! -d "/etc/php/$sys_phpversion/fpm/pool.d/" ]; then
if [ ! -d "$pool_internal" ]; then
local all_versions="$(multiphp_versions)"
if [ -n "$all_versions" ]; then
sys_phpversion="${all_versions##*\ }"
@@ -1730,4 +1795,31 @@ get_conf_d_name(){
else
echo "conf.d"
fi
}
# Get default php version
# hestia.conf should be enabled before function
get_system_default_php(){
declare -a local_versions
if [ "$LOCAL_PHP" == "yes" ]; then
for version in /opt/brepo/php*/etc/php-fpm.d/www.conf; do
local_ver=$(echo "$version" | awk -F"/" '{ print $4 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
if [ "$local_ver" != "php*" ]; then
local_versions+=("$local_ver")
fi
done
else
for version in /etc/opt/remi/php*/php-fpm.d/www.conf; do
local_ver=$(echo "$version" | awk -F"/" '{ print $5 }' | sed "s/php\([[:digit:]]\+\)/\1/g")
if [ "$local_ver" != "php*" ]; then
local_versions+=("$local_ver")
fi
done
fi
if [ ${#local_versions[@]} -eq 0 ]; then
local_php_ver="82"
else
local_php_ver="${local_versions[0]}"
fi
echo "$local_php_ver"
}

View File

@@ -118,11 +118,6 @@ upgrade_complete_message() {
echo "============================================================================="
echo
echo "Upgrade complete! If you encounter any issues or find a bug, "
echo "please take a moment to report it to us on GitHub at the URL below: "
echo "https://github.com/hestiacp/hestiacp/issues "
echo
echo "Read the release notes to learn about new fixes and features: "
echo "https://github.com/hestiacp/hestiacp/blob/release/CHANGELOG.md "
echo
echo "We hope that you enjoy using this version of Hestia Control Panel, "
echo "have a wonderful day! "
@@ -130,13 +125,6 @@ upgrade_complete_message() {
echo "Sincerely, "
echo "The Hestia Control Panel development team "
echo
echo "Web: https://www.hestiacp.com/ "
echo "Docs: https://docs.hestiacp.com/ "
echo "Forum: https://forum.hestiacp.com/ "
echo "GitHub: https://github.com/hestiacp/hestiacp/ "
echo
echo "Help support the Hestia Control Panel project by donating via PayPal: "
echo "https://www.hestiacp.com/donate "
echo
echo "Made with love & pride by the open-source community around the world. "
echo
@@ -148,8 +136,6 @@ upgrade_complete_message_log() {
echo
echo "============================================================================="
echo "UPGRADE COMPLETE. "
echo "Please report any issues on GitHub: "
echo "https://github.com/hestiacp/hestiacp/issues "
echo "============================================================================="
echo
$BIN/v-log-action "system" "Info" "Updates" "Update installed (Version: $new_version)."
@@ -219,17 +205,6 @@ upgrade_send_notification_to_email() {
echo "" >> $message_tmp_file
fi
echo "What's new: https://github.com/hestiacp/hestiacp/blob/$RELEASE_BRANCH/CHANGELOG.md" >> $message_tmp_file
echo >> $message_tmp_file
echo "What to do if you run into issues:" >> $message_tmp_file
echo "- Check our forums for possible solutions: https://forum.hestiacp.com" >> $message_tmp_file
echo "- File an issue report on GitHub: https://github.com/hestiacp/hestiacp/issues" >> $message_tmp_file
echo "" >> $message_tmp_file
echo "Help support the Hestia Control Panel project by donating via PayPal: https://www.hestiacp.com/donate" >> $message_tmp_file
echo "===================================================" >> $message_tmp_file
echo "Have a wonderful day," >> $message_tmp_file
echo "The Hestia Control Panel development team" >> $message_tmp_file
# Read back message from file and pass through to sendmail
cat $message_tmp_file | $send_mail -s "Update Installed - v${new_version}" $admin_email
rm -f $message_tmp_file

2
func_ruby/.bundle/config Normal file
View File

@@ -0,0 +1,2 @@
---
BUNDLE_PATH: "gems"

7
func_ruby/Gemfile Normal file
View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem "envbash"
gem "interface"
gem "shell"

22
func_ruby/Gemfile.lock Normal file
View File

@@ -0,0 +1,22 @@
GEM
remote: https://rubygems.org/
specs:
e2mmap (0.1.0)
envbash (1.0.1)
interface (1.0.5)
shell (0.8.1)
e2mmap
sync
sync (0.5.0)
PLATFORMS
ruby
x86_64-linux
DEPENDENCIES
envbash
interface
shell
BUNDLED WITH
2.5.16

View File

@@ -0,0 +1 @@
0.0.1

View File

@@ -0,0 +1,31 @@
#!/opt/brepo/ruby33/bin/ruby
class EmptyWorker < Kernel::ModuleCoreWorker
MODULE_ID = "empty_module"
def info
{
ID: 3,
NAME: MODULE_ID,
DESCR: "Just empty module for storing max module id",
REQ: "",
CONF: "",
}
end
implements IPluginInterface
end
module EmptyModule
def get_object
Proc.new { EmptyWorker.new }
end
module_function :get_object
end
class Kernel::PluginConfiguration
include EmptyModule
@@loaded_plugins[EmptyWorker::MODULE_ID] = EmptyModule.get_object
end

View File

@@ -0,0 +1,233 @@
#!/opt/brepo/ruby33/bin/ruby
require "shell"
class PassengerWorker < Kernel::ModuleCoreWorker
MODULE_ID = "passenger_manager"
def check_domains_with_passenger
dom_file = get_module_conf("domains.conf")
val = hestia_get_file_keys_value(dom_file)
if val.empty?
true
else
false
end
end
def info
{
ID: 2,
NAME: MODULE_ID,
DESCR: "Added passenger support for nginx",
REQ: "puppet_installer",
CONF: "yes",
}
end
def enable
log_file = get_log
f_inst_pp = get_module_paydata("passenger_installer.pp")
f_uninst_pp = get_module_paydata("passenger_uninstaller.pp")
if !check
inf = info
log("Req error, needed #{inf[:REQ]}")
"Req error, needed #{inf[:REQ]}"
else
begin
prepare_default_ruby_conf
log("install packages for passenger + nginx support: /usr/bin/puppet apply --detailed-exitcodes #{f_inst_pp}")
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_inst_pp}" 2>&1`
ex_status = $?.exitstatus
if ex_status.to_i == 0 || ex_status.to_i == 2
log(result_action)
super
else
log(result_action)
log("Try to disable action: /usr/bin/puppet apply --detailed-exitcodes #{f_uninst_pp}")
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_uninst_pp}" 2>&1`
"module installation error. See log #{log_file}"
end
rescue => e
log("module installation error #{e.message} #{e.backtrace.first}")
"module installation error. See log #{log_file}"
end
end
end
def disable
log_file = get_log
f_uninst_pp = get_module_paydata("passenger_uninstaller.pp")
if !check_domains_with_passenger
return log_return("Presents domains with passenger support disable it first")
end
begin
log("uninstall packages for passenger + nginx support")
log("Try to disable action: /usr/bin/puppet apply --detailed-exitcodes #{f_uninst_pp}")
result_action = `/usr/bin/puppet apply --detailed-exitcodes "#{f_uninst_pp}" 2>&1`
ex_status = $?.exitstatus
if ex_status.to_i == 0 || ex_status.to_i == 2
log(result_action)
super
else
log(result_action)
"module installation error. See log #{log_file}"
end
rescue => e
log("module installation error #{e.message} #{e.backtrace.first}")
"module installation error. See log #{log_file}"
end
end
def prepare_default_ruby_conf
ruby_conf_rubys = get_module_conf("rubys.conf")
return if File.exist?(ruby_conf_rubys)
arr = ["/usr/bin/ruby", "/opt/brepo/ruby33/bin/ruby"]
hestia_write_to_config_with_lock(ruby_conf_rubys, arr)
end
def return_rubys_from_conf
arr = []
ruby_conf_rubys = get_module_conf("rubys.conf")
return arr unless File.exist?(ruby_conf_rubys)
hestia_read_config_with_lock(ruby_conf_rubys)
end
def command(args)
return log_return("Not enough arguments. Needed command") if args.length < 1
m_command = args[0].strip
case m_command
when "get_rubys"
result = return_rubys_from_conf.map { |item| { "RUBY" => item } }
format = (args[1].nil? ? "shell" : args[1].strip)
hestia_print_array_of_hashes(result, format, "RUBY")
ACTION_OK
when "add_ruby"
path = args[1]
if path.nil?
log_return("Path to ruby should be specified. #{args}")
else
path = path.strip
if File.exist?(path)
rubys = return_rubys_from_conf
unless rubys.include? path
rubys << path
ruby_conf_rubys = get_module_conf("rubys.conf")
hestia_write_to_config_with_lock(ruby_conf_rubys, rubys)
end
ACTION_OK
else
log_return("File #{path} doesn't exists")
end
end
when "del_ruby"
path = args[1]
if path.nil?
log_return("Path to ruby should be specified. #{args}")
else
path = path.strip
rubys = return_rubys_from_conf
if rubys.include? path
rubys.delete(path)
ruby_conf_rubys = get_module_conf("rubys.conf")
hestia_write_to_config_with_lock(ruby_conf_rubys, rubys)
end
ACTION_OK
end
when "set_user_ruby"
domain = args[1]
ruby_ver = args[2]
log_mod = args[3]
if domain.nil? || ruby_ver.nil?
log_return("Domain or ruby version should be specified. #{args}")
else
if File.exist?(ruby_ver)
dom_file = get_module_conf("domains.conf")
if !log_mod.nil? && log_mod.to_s.strip == "on"
ruby_ver = "#{ruby_ver}|on"
end
hestia_save_file_key_pair(dom_file, domain, ruby_ver)
ACTION_OK
else
log_return("Ruby path doesn't exists. #{ruby_ver}. Args #{args}")
end
end
when "disable_user"
domain = args[1]
if domain.nil?
log_return("Domain should be specified. #{args}")
else
dom_file = get_module_conf("domains.conf")
hestia_save_file_key_pair(dom_file, domain, "")
ACTION_OK
end
when "get_user_ruby"
domain = args[1]
if domain.nil?
log_return("Domain should be specified. #{args}")
else
dom_file = get_module_conf("domains.conf")
format = (args[2].nil? ? "shell" : args[2].strip)
val = hestia_get_file_key_pair(dom_file, domain)
val_spl = val.split("|", 2)
result = Hash.new
result["RUBY"] = val_spl[0]
result["LOG"] = (val_spl.length > 1 ? val_spl[1] : "off")
a_result = []
a_result << result
hestia_print_array_of_hashes(a_result, format, "RUBY,LOG")
ACTION_OK
end
when "list_users_ruby"
dom_file = get_module_conf("domains.conf")
format = (args[1].nil? ? "shell" : args[1].strip)
val = hestia_get_file_keys_value(dom_file)
result = Array.new
val.each do |key, value|
vv = value.split("|", 2)
result << { "DOMAIN" => key, "RUBY" => vv[0], "LOG" => (vv.length > 1 ? vv[1] : "off") }
end
hestia_print_array_of_hashes(result, format, "DOMAIN,RUBY,LOG")
ACTION_OK
when "get_tpl_path"
result = [{ "RUBY_TPL" => get_module_paydata_dir }]
format = (args[1].nil? ? "shell" : args[1].strip)
hestia_print_array_of_hashes(result, format, "RUBY_TPL")
ACTION_OK
when "help"
puts "#{$0} passenger_manager COMMAND [OPTIONS] [json|csv|plain]"
puts "COMMANDS:"
puts " get_rubys - list all available rubys pathes"
puts " add_ruby [full_path_to_ruby_binary] - add ruby to list"
puts " del_ruby [full_path_to_ruby] - delete ruby from list"
puts " set_user_ruby [domain] [full_path_to_ruby_binary] [logging on or mpty] - set ruby for domain"
puts " disable_user [domain] - delete ruby for domain"
puts " get_user_ruby [domain] - show ruby path for domain or empty if not set"
puts " list_users_ruby - show rubys for all domains"
puts " get_tpl_path - show path for module's templates"
puts " help - help"
ACTION_OK
else
log_return("Unknown command. #{args}")
end
end
implements IPluginInterface
end
module PassengerModule
def get_object
Proc.new { PassengerWorker.new }
end
module_function :get_object
end
class Kernel::PluginConfiguration
include PassengerModule
@@loaded_plugins[PassengerWorker::MODULE_ID] = PassengerModule.get_object
end

View File

@@ -0,0 +1,50 @@
# Default Web Domain Template #
# DO NOT MODIFY THIS FILE! CHANGES WILL BE LOST WHEN REBUILDING DOMAINS #
#=========================================================================#
server {
listen %ip%:%proxy_ssl_port% ssl;
server_name %domain_idn% %alias_idn%;
root %docroot%
error_log /var/log/%web_system%/domains/%domain%.error.log error;
ssl_certificate %ssl_pem%;
ssl_certificate_key %ssl_key%;
ssl_stapling on;
ssl_stapling_verify on;
# TLS 1.3 0-RTT anti-replay
if ($anti_replay = 307) { return 307 https://$host$request_uri; }
if ($anti_replay = 425) { return 425; }
include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
passenger_enabled on;
passenger_user %user%;
passenger_group %user%;
passenger_ruby %rubypath%;
passenger_friendly_error_pages %rubylog%;
location / {
passenger_base_uri /;
passenger_app_root %docrtpriv%;
passenger_document_root %docroot%;
passenger_startup_file config.rb;
passenger_app_type rack;
}
location /error/ {
alias %home%/%user%/web/%domain%/document_errors/;
}
disable_symlinks if_not_owner from=%sdocroot%;
proxy_hide_header Upgrade;
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
}

View File

@@ -0,0 +1,35 @@
# Default Web Domain Template #
# DO NOT MODIFY THIS FILE! CHANGES WILL BE LOST WHEN REBUILDING DOMAINS #
#=========================================================================#
server {
listen %ip%:%proxy_port%;
server_name %domain_idn% %alias_idn%;
root %docroot%;
error_log /var/log/%web_system%/domains/%domain%.error.log error;
include %home%/%user%/conf/web/%domain%/nginx.forcessl.conf*;
location ~ /\.(?!well-known\/|file) {
deny all;
return 404;
}
passenger_enabled on;
passenger_user %user%;
passenger_group %user%;
passenger_ruby %rubypath%;
passenger_friendly_error_pages %rubylog%;
location / {
passenger_base_uri /;
passenger_app_root %docrtpriv%;
passenger_document_root %docroot%;
passenger_startup_file config.rb;
passenger_app_type rack;
}
disable_symlinks if_not_owner from=%docroot%;
include %home%/%user%/conf/web/%domain%/nginx.conf_*;
}

View File

@@ -0,0 +1,66 @@
package { 'rubygems-devel':
ensure => installed,
name => 'rubygems-devel',
provider => 'dnf',
}
-> package { 'rubygem-rake':
ensure => installed,
name => 'rubygem-rake',
provider => 'dnf',
}
-> package { 'ruby-devel':
ensure => installed,
name => 'ruby-devel',
provider => 'dnf',
}
-> package { 'rubygem-rack':
ensure => installed,
name => 'rubygem-rack',
provider => 'dnf',
}
-> package { 'alt-brepo-ruby33-devel':
ensure => installed,
name => 'alt-brepo-ruby33-devel',
provider => 'dnf',
}
-> package { 'alt-brepo-ruby33-rubygem-rake':
ensure => installed,
name => 'alt-brepo-ruby33-rubygem-rake',
provider => 'dnf',
}
-> package { 'passenger-devel':
ensure => installed,
name => 'passenger-devel',
provider => 'dnf',
}
-> package { 'passenger':
ensure => installed,
name => 'passenger',
provider => 'dnf',
}
-> package { 'nginx-passenger':
ensure => installed,
name => 'nginx-mod-http-passenger',
provider => 'dnf',
}
-> file { 'passenger.conf':
ensure => file,
path => '/etc/nginx/conf.d/passenger.conf',
content => 'passenger_root /usr/share/ruby/vendor_ruby/phusion_passenger/locations.ini;
passenger_ruby /usr/bin/ruby;
passenger_instance_registry_dir /var/run/passenger-instreg;
passenger_user_switching on;
passenger_env_var PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY 0;
passenger_env_var PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY 0;',
}
-> file { 'passenger_includer.conf':
ensure => file,
content => 'load_module modules/ngx_http_passenger_module.so;',
path => '/etc/nginx/conf.d/main/passenger.conf',
}
~> service { 'nginx_service':
ensure => running,
name => 'nginx',
provider => 'systemd',
hasrestart => true,
}

View File

@@ -0,0 +1,29 @@
package { 'nginx-mod-http-passenger':
ensure => absent,
name => 'nginx-mod-http-passenger',
provider => 'dnf',
}
-> package { 'passenger-devel':
ensure => absent,
name => 'passenger-devel',
provider => 'dnf',
}
-> package { 'passenger':
ensure => absent,
name => 'passenger',
provider => 'dnf',
}
-> file { 'passenger.conf':
ensure => absent,
path => '/etc/nginx/conf.d/passenger.conf',
}
-> file { 'passenger_includer.conf':
ensure => absent,
path => '/etc/nginx/conf.d/main/passenger.conf',
}
~> service { 'nginx_service':
ensure => running,
name => 'nginx',
provider => 'systemd',
hasrestart => true,
}

View File

@@ -0,0 +1,256 @@
#!/opt/brepo/ruby33/bin/ruby
class EmptyWorker < Kernel::ModuleCoreWorker
MODULE_ID = "php_brepo_modules"
def info
{
ID: 4,
NAME: MODULE_ID,
DESCR: "Module for managing of php modules for php's from brepo repository",
REQ: "",
CONF: "yes",
}
end
def enable
if $LOCAL_PHP == "yes"
super
else
log_return("PHP from brepo repository not enabled")
end
end
def get_list_of_installed_php
php_list = []
lst = Dir["/opt/brepo/php*/etc/php.ini"]
if lst.length.positive?
php_list = lst.select do |item|
%r{/opt/brepo/php\d+/etc/php\.ini} =~ item
end.map do |item|
res = item.match %r{/opt/brepo/php(?<ver>\d+)/etc/php\.ini}
res[:ver]
end
end
php_list
end
def get_list_of_installed_php_modules(php_ver)
php_modules = {}
php_list = get_list_of_installed_php
if php_list.include? php_ver
lst = Dir["/opt/brepo/php#{php_ver}/etc/mod-installed/*.ini"]
php_list_m = lst.map { |item| File.basename(item, ".ini") }.select { |item| item.strip != "" && !(item =~ %r{ioncube_loader_lin_}) }
lst_enabled = Dir["/opt/brepo/php#{php_ver}/etc/php.d/*.ini"]
php_list_i = {}
lst_enabled.each do |item|
fname = File.basename(item, ".ini")
if fname.strip != ""
if File.symlink? item
fname_n = File.readlink(item)
fname_n = File.basename(fname_n, ".ini")
php_list_i[fname_n] = fname unless fname_n.strip == ""
end
end
end
php_list_m.each do |item|
php_modules[item] = "disabled"
php_modules[item] = php_list_i[item] unless php_list_i[item].nil?
end
end
php_modules
end
def get_php_module_description(module_name)
case module_name
when "bcmath"
"Модуль математических операций с числами произвольной точности"
when "curl"
"Поддержка curl функций из библиотеки libcurl"
when "dba"
"Эти функции — основа для доступа к базам данных наподобие Berkeley DB"
when "dom"
"Модуль DOM разрешает работать в PHP с XML- и HTML-документами через DOM API"
when "gd"
"Функции работы с изображениями"
when "imap"
"Эти функции позволяют работать с протоколом IMAP, а также NNTP, POP3 и локальными методами доступа к почтовому ящику."
when "intl"
"Модуль интернационализации"
when "ioncube"
"Модуль котрый производит деобфускацию кода, написанного на языке php и закодированного утилитами из набора ioncube"
when "ioncube_loader_lin_7.4"
"Модуль котрый производит деобфускацию кода, написанного на языке php и закодированного утилитами из набора ioncube"
when "json"
"Поддержка json в PHP"
when "ldap"
"Поддержка работы с LDAP в PHP"
when "mbstring"
"Поддержка работы с многобайтовыми строками"
when "memcache"
"Модуль Memcache предоставляет удобный процедурный и объектно-ориентированный интерфейс к memcached, высокоэффективному кеширующему демону, который был специально разработан для снижения нагрузки на базу данных в динамических веб приложениях"
when "mysqli"
"Модуль mysqli позволяет вам получить доступ к функциональности, которую предоставляет MySQL версии 4.1 и выше"
when "mysqlnd"
"Встроенный драйвер MySQL"
when "odbc"
"В дополнение к обычной поддержке ODBC, функции Unified ODBC в PHP позволяют получить доступ к нескольким базам данных, которые позаимствовали семантику ODBC API для реализации своего собственного API."
when "opcache"
"Модуль OPcache сохраняет предкомпилированный байт-код скриптов в разделяемой памяти. Кеширование операционного PHP-кода повышает производительность и помогает избегать загрузки и анализа скриптов при каждом запросе."
when "pdo"
"Модуль PDO определяет легковесный и непротиворечивый интерфейс доступа к базам данных в PHP."
when "pdo_dblib"
"PDO_DBLIB: драйвер модуля PDO для СУБД Microsoft SQL Server и Sybase"
when "pdo_mysql"
"PDO_MYSQL: драйвер модуля PDO для СУБД MySQL"
when "pdo_odbc"
"PDO_ODBC: драйвер модуля PDO для СУБД ODBC и DB2"
when "pdo_pgsql"
"PDO_PGSQL: драйвер модуля PDO для СУБД PostgreSQL"
when "pdo_sqlite"
"PDO_SQLITE: драйвер модуля PDO для СУБД SQLite"
when "pgsql"
"Модуль поддержки взаимодействия PHP с PostgreSQL"
when "phar"
"Модуль phar предоставляет возможность поместить целое PHP-приложение в один-единственный файл c именем phar (PHP Archive) для простого распространения и установки"
when "posix"
"Этот модуль содержит интерфейс к функциям, определённым в стандарте IEEE 1003.1 (POSIX.1), которые не доступны с помощью других средств."
when "pspell"
"Функции позволяют проверять правописание слова и предлагают варианты исправления."
when "snmp"
"Модуль SNMP предоставляет простой и удобный набор инструментов для управления удалёнными устройствами через Simple Network Management Protocol (простой протокол управления сетями)"
when "soap"
"Модуль SOAP может использоваться для написания как серверной, так и клиентской части. Он реализует спецификации » SOAP 1.1, » SOAP 1.2 и » WSDL 1.1."
when "sodium"
"Sodium — современная, простая в работе программная библиотека для шифрования и дешифрования данных, выполнения операций с подписями, хеширования паролей и других криптографических целей"
when "sysvmsg"
"Модуль поддержки сообщений System V"
when "sysvsem"
"Поддержка семафоров"
when "sysvshm"
"Поддержка разделяемой памяти"
when "tidy"
"Модуль коррекции разметки tidy"
when "xmlreader"
"Модуль XMLReader — синтаксический анализатор XML-документов"
when "xmlrpc"
"Функции модуля помогают писать клиентский или серверный код по правилам стандарта XML-RPC"
when "xmlwriter"
"Модуль XMLWriter оборачивает API-интерфейс парсера xmlWriter, который входит в состав модуля libxml."
when "xsl"
"Модуль XSL реализует XSL-стандарт путём XSLT-преобразований, которые выполняет через библиотеку libxslt"
when "zip"
"Модуль позволяет легко читать и записывать как в сами сжатые ZIP-архивы, так и в файлы внутри них"
else
"нет описания"
end
end
def disable_module(php_ver, module_name)
php_mods = get_list_of_installed_php_modules(php_ver)
return if php_mods[module_name].nil?
if File.exist? ("/opt/brepo/php#{php_ver}/etc/php.d/#{php_mods[module_name]}.ini")
File.unlink("/opt/brepo/php#{php_ver}/etc/php.d/#{php_mods[module_name]}.ini")
end
end
def enable_module(php_ver, module_name)
php_mods = get_list_of_installed_php_modules(php_ver)
return if php_mods[module_name].nil?
if php_mods[module_name] == "disabled"
case module_name
when "opcache"
File.symlink("/opt/brepo/php#{php_ver}/etc/mod-installed/#{module_name}.ini", "/opt/brepo/php#{php_ver}/etc/php.d/10-#{module_name}.ini")
when "mysqli", "pdo_mysql", "xmlreader", "zip"
File.symlink("/opt/brepo/php#{php_ver}/etc/mod-installed/#{module_name}.ini", "/opt/brepo/php#{php_ver}/etc/php.d/30-#{module_name}.ini")
else
File.symlink("/opt/brepo/php#{php_ver}/etc/mod-installed/#{module_name}.ini", "/opt/brepo/php#{php_ver}/etc/php.d/20-#{module_name}.ini")
end
end
end
def command(args)
return log_return("Not enough arguments. Needed command") if args.length < 1
m_command = args[0].strip
case m_command
when "php_list"
result = get_list_of_installed_php.map { |item| { "PHPVER" => item } }
format = (args[1].nil? ? "shell" : args[1].strip)
hestia_print_array_of_hashes(result, format, "PHPVER")
ACTION_OK
when "php_modules"
vers = args[1]
if vers.nil?
log_return("Verssion should be specified. #{args}")
else
vers = vers.strip
modules_list = get_list_of_installed_php_modules(vers)
m_keys = modules_list.keys.sort
result = []
m_keys.each do |kk|
tmp_hash = {}
tmp_hash["PHPVER"] = vers
tmp_hash["MODNAME"] = kk
tmp_hash["STATE"] = modules_list[kk]
tmp_hash["DESCR"] = get_php_module_description(kk)
result << tmp_hash
end
format = (args[2].nil? ? "shell" : args[2].strip)
hestia_print_array_of_hashes(result, format, "PHPVER,MODNAME,STATE,DESCR")
ACTION_OK
end
when "php_enable"
vers = args[1]
mod_n = args[2]
if vers.nil? || mod_n.nil?
log_return("Verssion and module name should be specified. #{args}")
else
vers = vers.strip
mod_n = mod_n.strip
enable_module(vers, mod_n)
ACTION_OK
end
when "php_disable"
vers = args[1]
mod_n = args[2]
if vers.nil? || mod_n.nil?
log_return("Verssion and module name should be specified. #{args}")
else
vers = vers.strip
mod_n = mod_n.strip
disable_module(vers, mod_n)
ACTION_OK
end
when "help"
puts "#{$0} php_brepo_modules COMMAND [OPTIONS] [json|csv|plain]"
puts "COMMANDS:"
puts " php_list - list all local php installed"
puts " php_modules [php_ver] - list available php module"
puts " php_enable [php_ver] [module_name] - enable php module"
puts " php_disable [php_ver] [module_name] - disable php module"
puts " help - help"
ACTION_OK
else
log_return("Unknown command. #{args}")
end
end
implements IPluginInterface
end
module EmptyModule
def get_object
Proc.new { EmptyWorker.new }
end
module_function :get_object
end
class Kernel::PluginConfiguration
include EmptyModule
@@loaded_plugins[EmptyWorker::MODULE_ID] = EmptyModule.get_object
end

View File

@@ -0,0 +1,117 @@
#!/opt/brepo/ruby33/bin/ruby
require "shell"
require "date"
class PuppetWorker < Kernel::ModuleCoreWorker
MODULE_ID = "puppet_installer"
def info
{
ID: 1,
NAME: MODULE_ID,
DESCR: "Added puppet support, needed for another modules",
REQ: "",
CONF: "",
}
end
def enable
log_file = get_log
date = DateTime.now
bkp_name = date.strftime("%Y_%m_%d_%H_%M_%S")
if !check
inf = info
log("Req error, needed #{inf[:REQ]}")
"Req error, needed #{inf[:REQ]}"
else
Shell.def_system_command("dnf", "/usr/bin/dnf")
Shell.def_system_command("gem", "/usr/bin/gem")
Shell.verbose = true
Shell.debug = false
sh = Shell.new
begin
%x( /usr/bin/rpm -q puppet )
unless $?.success?
log("install puppet packages")
sh.transact do
dnf("install", "-y", "puppet", "ruby", "rubygems", "puppet-stdlib") > log_file
gem("cleanup", "thor") > log_file
end
else
log("puppet installed")
end
log("prepare puppet configuration")
if File.exist?("/etc/puppet/puppet.conf")
File.rename("/etc/puppet/puppet.conf", "/etc/puppet/puppet.conf.#{bkp_name}")
end
puppet_conf = <<~CONF
[main]
confdir=/etc/puppet
logdir=/var/log/puppet
vardir=/var/lib/puppet
ssldir=/var/lib/puppet/ssl
rundir=/var/run/puppet
factpath=$confdir/facter
environmentpath=$confdir/environments
basemodulepath=/usr/share/puppet/modules
default_manifest=$confdir/manifests
environment_timeout = unlimited
manifests_path =$confdir/manifests
CONF
File.open("/etc/puppet/puppet.conf", "w") do |f|
f.puts(puppet_conf)
end
log("prepare hiera configuration")
if File.exist?("/etc/puppet/hiera.yaml")
File.rename("/etc/puppet/hiera.yaml", "/etc/puppet/hiera.yaml.#{bkp_name}")
end
hiera_conf = <<~CONF
---
version: 5
hierarchy:
- name: "yaml"
datadir: /tmp/puppet/hieradata
# data is staged to a local directory by the puppet-manifest-apply.sh script
data_hash: yaml_data
paths:
- runtime.yaml
- host.yaml
- secure_system.yaml
- system.yaml
- secure_static.yaml
- static.yaml
- personality.yaml
- global.yaml
CONF
File.open("/etc/puppet/hiera.yaml", "w") do |f|
f.puts(hiera_conf)
end
log("create manifests directory")
sh.transact do
((mkdir("/etc/puppet/manifests")) > log_file) unless File.exist?("/etc/puppet/manifests")
end
super
rescue => e
log("module installation error #{e.message} #{e.backtrace.first}")
"module installation error. See log #{log_file}"
end
end
end
implements IPluginInterface
end
module PuppetModule
def get_object
Proc.new { PuppetWorker.new }
end
module_function :get_object
end
class Kernel::PluginConfiguration
include PuppetModule
@@loaded_plugins[PuppetWorker::MODULE_ID] = PuppetModule.get_object
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,6 @@
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
# Specify your gem's dependencies in e2mmap.gemspec
gemspec

View File

@@ -0,0 +1,22 @@
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -0,0 +1,85 @@
# Exception2MessageMapper
Helper module for easily defining exceptions with predefined messages.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'e2mmap'
```
And then execute:
$ bundle
Or install it yourself as:
$ gem install e2mmap
## Usage
1.
```
class Foo
extend Exception2MessageMapper
def_e2message ExistingExceptionClass, "message..."
def_exception :NewExceptionClass, "message..."[, superclass]
...
end
```
2.
```
module Error
extend Exception2MessageMapper
def_e2message ExistingExceptionClass, "message..."
def_exception :NewExceptionClass, "message..."[, superclass]
...
end
class Foo
include Error
...
end
foo = Foo.new
foo.Fail ....
```
3.
```
module Error
extend Exception2MessageMapper
def_e2message ExistingExceptionClass, "message..."
def_exception :NewExceptionClass, "message..."[, superclass]
...
end
class Foo
extend Exception2MessageMapper
include Error
...
end
Foo.Fail NewExceptionClass, arg...
Foo.Fail ExistingExceptionClass, arg...
```
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/e2mmap.
## License
The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).

View File

@@ -0,0 +1 @@
require "bundler/gem_tasks"

View File

@@ -0,0 +1,14 @@
#!/usr/bin/env ruby
require "bundler/setup"
require "e2mmap"
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require "irb"
IRB.start(__FILE__)

View File

@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here

View File

@@ -0,0 +1,26 @@
begin
require_relative "lib/e2mmap/version"
rescue LoadError
# for Ruby core repository
require_relative "e2mmap/version"
end
Gem::Specification.new do |spec|
spec.name = "e2mmap"
spec.version = Exception2MessageMapper::VERSION
spec.authors = ["Keiju ISHITSUKA"]
spec.email = ["keiju@ruby-lang.org"]
spec.summary = %q{Module for defining custom exceptions with specific messages.}
spec.description = %q{Module for defining custom exceptions with specific messages.}
spec.homepage = "https://github.com/ruby/e2mmap"
spec.license = "BSD-2-Clause"
spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "e2mmap.gemspec", "lib/e2mmap.rb", "lib/e2mmap/version.rb"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.16"
spec.add_development_dependency "rake", "~> 10.0"
end

View File

@@ -0,0 +1,177 @@
# frozen_string_literal: true
#
#--
# e2mmap.rb - for Ruby 1.1
# $Release Version: 2.0$
# $Revision: 1.10 $
# by Keiju ISHITSUKA
#
#++
#
# Helper module for easily defining exceptions with predefined messages.
#
# == Usage
#
# 1.
# class Foo
# extend Exception2MessageMapper
# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
#
# 2.
# module Error
# extend Exception2MessageMapper
# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
# class Foo
# include Error
# ...
# end
#
# foo = Foo.new
# foo.Fail ....
#
# 3.
# module Error
# extend Exception2MessageMapper
# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
# ...
# end
# class Foo
# extend Exception2MessageMapper
# include Error
# ...
# end
#
# Foo.Fail NewExceptionClass, arg...
# Foo.Fail ExistingExceptionClass, arg...
#
#
module Exception2MessageMapper
E2MM = Exception2MessageMapper # :nodoc:
def E2MM.extend_object(cl)
super
cl.bind(self) unless cl < E2MM
end
def bind(cl)
self.module_eval "#{<<-"begin;"}\n#{<<-"end;"}", __FILE__, __LINE__+1
begin;
def Raise(err = nil, *rest)
Exception2MessageMapper.Raise(self.class, err, *rest)
end
alias Fail Raise
class << self
undef included
end
def self.included(mod)
mod.extend Exception2MessageMapper
end
end;
end
# Fail(err, *rest)
# err: exception
# rest: message arguments
#
def Raise(err = nil, *rest)
E2MM.Raise(self, err, *rest)
end
alias Fail Raise
alias fail Raise
# def_e2message(c, m)
# c: exception
# m: message_form
# define exception c with message m.
#
def def_e2message(c, m)
E2MM.def_e2message(self, c, m)
end
# def_exception(n, m, s)
# n: exception_name
# m: message_form
# s: superclass(default: StandardError)
# define exception named ``c'' with message m.
#
def def_exception(n, m, s = StandardError)
E2MM.def_exception(self, n, m, s)
end
#
# Private definitions.
#
# {[class, exp] => message, ...}
@MessageMap = {}
# E2MM.def_e2message(k, e, m)
# k: class to define exception under.
# e: exception
# m: message_form
# define exception c with message m.
#
def E2MM.def_e2message(k, c, m)
E2MM.instance_eval{@MessageMap[[k, c]] = m}
c
end
# E2MM.def_exception(k, n, m, s)
# k: class to define exception under.
# n: exception_name
# m: message_form
# s: superclass(default: StandardError)
# define exception named ``c'' with message m.
#
def E2MM.def_exception(k, n, m, s = StandardError)
e = Class.new(s)
E2MM.instance_eval{@MessageMap[[k, e]] = m}
k.module_eval {remove_const(n)} if k.const_defined?(n, false)
k.const_set(n, e)
end
# Fail(klass, err, *rest)
# klass: class to define exception under.
# err: exception
# rest: message arguments
#
def E2MM.Raise(klass = E2MM, err = nil, *rest)
if form = e2mm_message(klass, err)
b = $@.nil? ? caller(1) : $@
b.shift if b[0] =~ /^#{Regexp.quote(__FILE__)}:/
raise err, sprintf(form, *rest), b
else
E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
end
end
class << E2MM
alias Fail Raise
end
def E2MM.e2mm_message(klass, exp)
for c in klass.ancestors
if mes = @MessageMap[[c,exp]]
m = klass.instance_eval('"' + mes + '"')
return m
end
end
nil
end
class << self
alias message e2mm_message
end
E2MM.def_exception(E2MM,
:ErrNotRegisteredException,
"not registered exception(%s)")
end

View File

@@ -0,0 +1,3 @@
module Exception2MessageMapper
VERSION = "0.1.0"
end

View File

@@ -0,0 +1,18 @@
root = true
# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
indent_style = space
indent_size = 4
tab_width = 8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.{json,rb,yaml,yml}]
indent_size = 2
# Tab indents for Makefile
[Makefile]
indent_style = tab

View File

@@ -0,0 +1,12 @@
sudo: false
language: ruby
cache: bundler
rvm:
- 2.1
- 2.2
- 2.3.3
- 2.4.0
install:
- bundle
script:
- rake

View File

@@ -0,0 +1,2 @@
source "https://rubygems.org"
gemspec

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Scampersand LLC
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,71 @@
# envbash
[![gem](https://img.shields.io/gem/v/envbash.svg?style=plastic)](https://rubygems.org/gems/envbash)
[![travis](https://img.shields.io/travis/scampersand/envbash-ruby/master.svg?style=plastic)](https://travis-ci.org/scampersand/envbash-ruby?branch=master)
[![codecov](https://img.shields.io/codecov/c/github/scampersand/envbash-ruby/master.svg?style=plastic)](https://codecov.io/gh/scampersand/envbash-ruby/branch/master)
Ruby gem for sourcing a bash script to augment the environment.
## Rationale
[12-factor apps](https://12factor.net/) require
[configuration loaded from the environment](https://12factor.net/config).
That's [easy on a platform like Heroku](https://devcenter.heroku.com/articles/config-vars),
where the environment is preset by the user with commands like
`heroku config:set`. But it's messier in development and non-Heroku
deployments, where the environment might need to be loaded from a file.
This package provides a mechanism for sourcing a Bash script to update
Ruby's environment (`ENV`). There are reasons for using a Bash script
instead of another configuration language:
1. Environment variable keys and values should always be strings. Using a Bash
script to update the environment enforces that restriction, so there won't
be surprises when you deploy into something like Heroku later on.
2. Using a script means that the values can be sourced into a Bash shell,
something that's non-trivial if you use a different config language.
3. For better or worse, using a script means that environment variables can be
set using the full power of the shell, including reading from other files.
Commonly the external file is called `env.bash`, hence the name of this project.
## Installation
Install from [RubyGems](https://rubygems.org/gems/envbash)
gem install envbash
or in your Gemfile:
gem 'envbash'
## Usage
Call `EnvBash.load` to source a Bash script into the current Ruby process.
Any variables that are set in the script, regardless of whether they are
explicitly exported, will be added to the process environment.
For example, given `env.bash` with the following content:
```bash
FOO='bar baz qux'
```
This can be loaded into Ruby:
```ruby
require 'envbash'
EnvBash.load('env.bash')
puts ENV['FOO'] #=> bar baz qux
```
## Legal
Copyright 2017 [Scampersand LLC](https://scampersand.com)
Released under the [MIT license](https://github.com/scampersand/envbash-ruby/blob/master/LICENSE)

View File

@@ -0,0 +1,13 @@
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test'
# make sure helper.rb is loaded first, to start simplecov
test.test_files = FileList['test/helper.rb', 'test/test*.rb']
end
task :default => :test
# this adds "rake build" to make pkg/envbash-*.gem
require 'bundler/setup'
Bundler::GemHelper.install_tasks

View File

@@ -0,0 +1,19 @@
Gem::Specification.new do |spec|
spec.name = "envbash"
spec.summary = "Source env.bash script to update environment"
spec.version = "1.0.1"
spec.authors = ["Aron Griffis"]
spec.email = "aron@scampersand.com"
spec.homepage = "https://github.com/scampersand/envbash-ruby"
spec.licenses = ["MIT"]
spec.files = `git ls-files -z`.split("\x0")
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "codecov"
spec.add_development_dependency "minitest"
spec.add_development_dependency "minitest-assert_errors"
spec.add_development_dependency "rake"
end

View File

@@ -0,0 +1,2 @@
require_relative 'envbash/load'
require_relative 'envbash/read'

View File

@@ -0,0 +1,16 @@
require_relative 'read'
module EnvBash
def EnvBash.load(envbash, into: ENV, override: false, remove: false, **kwargs)
loaded = read(envbash, **kwargs)
is_env = into.equal? ENV
into = into.to_h if is_env
if loaded
into.select! {|k| loaded.include? k} if remove
loaded.reject! {|k| into.include? k} unless override
into.merge! loaded
end
ENV.replace into if is_env
end
end

View File

@@ -0,0 +1,62 @@
require 'open3'
require 'shellwords'
module EnvBash
FIXUPS = %w{_ OLDPWD PWD SHLVL}
class ScriptExitedEarly < StandardError
end
def EnvBash.read(envbash, bash: 'bash', env: ENV, missing_ok: false, fixups: FIXUPS)
# make sure the file exists and is readable.
# alternatively we could test File.readable?(envbash) but this approach
# raises Errno::ENOENT or Errno::EACCES which is what we want.
begin
File.open(envbash).close
rescue Errno::ENOENT
return if missing_ok
raise
end
# construct an inline script which sources env.bash then prints the
# resulting environment so it can be eval'd back into this process.
inline = <<-EOT
set -a
source #{envbash.shellescape} >/dev/null
#{Gem.ruby.shellescape} -e 'p ENV'
EOT
# Process.spawn treats env as overriding ENV, and anything that should be
# omitted needs to have a nil value. If env == ENV then this is a noop.
env = Hash[ENV.keys.map {|k| [k, nil]}].merge(env)
# run the inline script with bash -c, capturing stdout. if there is any
# error output from env.bash, it will pass through to stderr.
# exit status is ignored.
output, _ = Open3.capture2(env, 'bash', '-c', inline, :in=>"/dev/null")
# the only stdout from the inline script should be
# `p ENV` so there should be no syntax errors eval'ing this. however there
# will be no output to eval if the sourced env.bash exited early, and that
# indicates script failure.
raise ScriptExitedEarly if output.empty?
# the eval'd output should return a hash.
nenv = eval(output)
# there are a few environment variables that vary between this process and
# running the inline script with bash -c, but are certainly not part of the
# intentional settings in env.bash.
for f in fixups
if env[f] # not .include? because env might have nil values
nenv[f] = env[f]
else
nenv.delete(f)
end
end
nenv
end
end

View File

@@ -0,0 +1,10 @@
require 'simplecov'
SimpleCov.start
if ENV['CI'] == 'true'
require 'codecov'
SimpleCov.formatter = SimpleCov::Formatter::Codecov
end
require 'minitest/autorun'
require 'minitest/assert_errors'

View File

@@ -0,0 +1,74 @@
require_relative 'helper'
require 'envbash'
class TestLoad < Minitest::Test
def setup
@orig = ENV.to_h
ENV['A'] = 'A'
ENV['B'] = 'B'
ENV['C'] = 'C'
ENV.delete('D')
@loaded = ENV.to_h.merge('A'=>'a', 'D'=>'d')
@loaded.delete('B')
end
def teardown
ENV.replace(@orig)
end
def test_load_no_override_no_remove
EnvBash.stub :read, @loaded do
# the first argument doesn't matter since read is stubbed
EnvBash.load('')
end
assert_equal ENV['A'], 'A' # NOT overridden
assert_equal ENV['B'], 'B' # NOT removed
assert_equal ENV['C'], 'C' # inherited
assert_equal ENV['D'], 'd' # loaded
end
def test_load_override_no_remove
EnvBash.stub :read, @loaded do
# the first argument doesn't matter since read is stubbed
EnvBash.load('', override: true)
end
assert_equal ENV['A'], 'a' # overridden
assert_equal ENV['B'], 'B' # NOT removed
assert_equal ENV['C'], 'C' # inherited
assert_equal ENV['D'], 'd' # loaded
end
def test_load_no_override_remove
EnvBash.stub :read, @loaded do
# the first argument doesn't matter since read is stubbed
EnvBash.load('', remove: true)
end
assert_equal ENV['A'], 'A' # NOT overridden
assert ! ENV.include?('B') # removed
assert_equal ENV['C'], 'C' # inherited
assert_equal ENV['D'], 'd' # loaded
end
def test_load_override_remove
EnvBash.stub :read, @loaded do
# the first argument doesn't matter since read is stubbed
EnvBash.load('', override: true, remove: true)
end
assert_equal ENV['A'], 'a' # overridden
assert ! ENV.include?('B') # removed
assert_equal ENV['C'], 'C' # inherited
assert_equal ENV['D'], 'd' # loaded
end
def test_load_into
orig = ENV.to_h
into = {}
EnvBash.stub :read, {'A'=>'B'} do
# the first argument doesn't matter since read is stubbed
EnvBash.load('', into: into)
end
assert_equal into, {'A'=>'B'}
assert_equal ENV.to_h, orig
end
end

View File

@@ -0,0 +1,95 @@
require_relative 'helper'
require 'fileutils'
require 'tmpdir'
require 'envbash'
class TestRead < Minitest::Test
def setup
@tmpdir = Dir.mktmpdir
@envbash = File.join @tmpdir, 'env.bash'
@orig = ENV.to_h
end
def teardown
ENV.replace(@orig)
FileUtils.rm_rf(@tmpdir)
end
def test_read_missing_not_ok
assert_error_raised(nil, Errno::ENOENT) do
EnvBash.read @envbash
end
end
def test_read_missing_ok
assert_no_error do
EnvBash.read @envbash, missing_ok: true
end
end
def test_read_permission_error
FileUtils.chmod 0, @tmpdir
assert_error_raised(nil, Errno::EACCES) do
EnvBash.read @envbash
end
end
def test_read_empty
FileUtils.touch @envbash
result = EnvBash.read @envbash
assert_equal result, @orig
end
def test_read_normal
ENV.delete('FOO')
orig = ENV.to_h # separate from @orig
File.open(@envbash, 'w') do |f|
f.write 'FOO=BAR'
end
result = EnvBash.read @envbash
assert_equal result['FOO'], 'BAR'
result.delete('FOO')
assert_equal result, orig
end
def test_read_error
File.open(@envbash, 'w') do |f|
# stderr doesn't matter, nor does final status.
f.write "echo 'okay!' >&2\nfalse"
end
result = EnvBash.read @envbash
assert_equal result, @orig
end
def test_read_exit
File.open(@envbash, 'w') do |f|
f.write 'exit'
end
assert_error_raised(nil, EnvBash::ScriptExitedEarly) do
EnvBash.read @envbash
end
end
def test_read_env
File.open(@envbash, 'w') do |f|
f.write 'FOO=BAR'
end
result = EnvBash.read @envbash, env: {}
assert_equal result, {'FOO'=>'BAR'}
end
def test_read_fixups
File.open(@envbash, 'w') do |f|
f.write 'A=B; C=D; E=F; G=H'
end
myenv = {'A'=>'Z', 'E'=>'F'}
result = EnvBash.read @envbash, env: myenv, fixups: ['A', 'C']
# there will be extra stuff in result since fixups is overridden, so can't
# test strict equality.
assert_equal result['A'], 'Z' # fixups, myenv, env.bash
assert !result.include?('C') # fixups, not myenv, env.bash
assert_equal result['E'], 'F' # not fixups, myenv, env.bash
assert_equal result['G'], 'H' # not fixups, not myenv, env.bash
end
end

View File

@@ -0,0 +1,30 @@
== 1.0.4 - 8-Jan-2016
* This gem is now signed.
* The gem related tasks in the Rakefile now assume Rubygems 2.x.
== 1.0.3 - 12-Oct-2014
* Rakefile, gemspec and README updates.
== 1.0.2 - 7-Oct-2009
* Fixed packaging bug in the gemspec, and made some other minor changes.
* Added the 'gem' rake task.
* Updated copyright and license in the README.
== 1.0.1 - 29-Jul-2009
* Now compatible with Ruby 1.9.x.
* Replaced the install.rb with a Rakefile and various tasks.
* Updated the license to Artistic 2.0.
* Added test-unit 2.x as a development dependency and refactored the test
suite to take advantage of some of its features.
* Renamed the test file to test_interface.rb.
* Renamed the example programs to all start with 'example_' to avoid any
possible confusion with actual test suites.
* Added rake tasks for running the example programs.
* Updated and refactored the gemspec.
== 1.0.0 - 5-Jun-2005
* Re-released on RubyForge.
* Some test suite and doc changes.
== 0.1.0 - 9-May-2004
* Initial release

View File

@@ -0,0 +1,12 @@
* CHANGES
* MANIFEST
* README
* Rakefile
* interface.gemspec
* certs/djberg96_pub.pem
* examples/example_instance.rb
* examples/example_interface.rb
* examples/example_sub.rb
* examples/example_unrequire.rb
* lib/interface.rb
* test/test_interface.rb

View File

@@ -0,0 +1,74 @@
== Description
This module provides Java style interfaces for Ruby, including a fairly
similar syntax. I don't necessarily believe in interfaces, but I wanted to
put it out there as proof that it could be done. Frankly, Java needs mixins
more than Ruby needs interfaces, but here you go.
== Installation
gem install interface
== Synopsis
require 'interface'
MyInterface = interface{
required_methods :foo, :bar, :baz
}
# Raises an error until 'baz' is defined
class MyClass
def foo
puts "foo"
end
def bar
puts "bar"
end
implements MyInterface
end
== General Notes
Subinterfaces work as well. See the test_sub.rb file under the 'test'
directory for a sample.
== Developer's Notes
A discussion on IRC with Mauricio Fernandez got us talking about traits.
During that discussion I remembered a blog entry by David Naseby. I
revisited his blog entry and took a closer look:
http://ruby-naseby.blogspot.com/2008/11/traits-in-ruby.html
Keep in mind that I also happened to be thinking about Java at the moment
because of a recent job switch that involved coding in Java. I was also
trying to figure out what the purpose of interfaces were.
As I read the first page of David Naseby's article I realized that,
whether intended or not, he had implemented a rudimentary form of interfaces
for Ruby. When I discovered this, I talked about it some more with Mauricio
and he and I (mostly him) fleshed out the rest of the module, including some
syntax improvements. The result is syntax and functionality that is nearly
identical to Java.
I should note that, although I am listed as the author, this was mostly the
combined work of David Naseby and Mauricio Fernandez. I just happened to be
the guy that put it all together.
== Acknowledgements
This module was largely inspired and somewhat copied from a post by
David Naseby (see URL above). It was subsequently modified almost entirely
by Mauricio Fernandez through a series of discussions on IRC.
== Copyright
(C) 2004-2016 Daniel J. Berger
All rights reserved.
== Warranty
This package is provided "as is" and without any express or
implied warranties, including, without limitation, the implied
warranties of merchantability and fitness for a particular purpose.
== License
Artistic 2.0
== Author
Daniel J. Berger

View File

@@ -0,0 +1,50 @@
require 'rake'
require 'rake/clean'
require 'rake/testtask'
CLEAN.include("**/*.gem", "**/*.rbc")
namespace :gem do
desc "Create the interface gem"
task :create => [:clean] do
require 'rubygems/package'
spec = eval(IO.read('interface.gemspec'))
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
Gem::Package.build(spec, true)
end
desc "Install the interface gem"
task :install => [:create] do
file = Dir["*.gem"].first
sh "gem install -l #{file}"
end
end
namespace :example do
desc 'Run the example_instance.rb sample program'
task :instance do
ruby '-Ilib examples/example_instance.rb'
end
desc 'Run the example_interface.rb sample program'
task :interface do
ruby '-Ilib examples/example_interface.rb'
end
desc 'Run the example_sub.rb sample program'
task :sub do
ruby '-Ilib examples/example_sub.rb'
end
desc 'Run the example_unrequire.rb sample program'
task :unrequire do
ruby '-Ilib examples/example_unrequire.rb'
end
end
Rake::TestTask.new do |t|
t.verbose = true
t.warning = true
end
task :default => :test

View File

@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
/3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
-----END CERTIFICATE-----

View File

@@ -0,0 +1,30 @@
#######################################################################
# example_instance.rb
#
# Sample program to demonstrate extending an interface to an instance
# of a class. You can run this program via the 'rake example:instance'
# task. Modify as you see fit.
#######################################################################
require 'interface'
MyInterface = interface{
required_methods :foo, :bar
}
class Foo
def foo; end
def bar; end
end
class Bar
end
f = Foo.new
f.extend(MyInterface)
b = Bar.new
# This will blow up
class << b
include MyInterface
end

View File

@@ -0,0 +1,28 @@
#######################################################################
# example_interface.rb
#
# Sample test script that demonstrates a typical interface. You can
# run this example via the 'rake example:interface' task. Modify this
# code as you see fit.
#######################################################################
require 'interface'
MyInterface = interface{
required_methods :foo, :bar
}
class MyClass
def foo; end
def bar; end
include MyInterface
end
=begin
# Raises an error until bar is defined
class Foo
def foo
puts "foo"
end
include MyInterface
end
=end

View File

@@ -0,0 +1,34 @@
#######################################################################
# example_sub.rb
#
# Sample program to demonstrate extending a sub-interface. You can
# run this program via the 'rake example:sub' task. Modify this code
# as you see fit.
#######################################################################
require 'interface'
module MyInterface
extend Interface
required_methods :foo, :bar
end
module MySubInterface
extend Interface
extend MyInterface
required_methods :baz
end
class MyClass
def baz; end
def bar; end
def foo; end
include MySubInterface
end
=begin
# Raises an error
class MyClass
def baz; end
include MyInterface
end
=end

View File

@@ -0,0 +1,26 @@
###########################################################################
# example_unrequire.rb
#
# Sample test script for to verify that unrequired_methods works properly.
# You can run this code via the 'rake example:unrequire' rake task. Modify
# this code as you see fit.
###########################################################################
require 'interface'
MyInterface = interface{
required_methods :foo, :bar
}
# require foo and baz, but not bar
MySubInterface = interface{
extends MyInterface
required_methods :baz
unrequired_methods :bar
}
# No error
class MyClass
def foo; end
def baz; end
include MySubInterface
end

View File

@@ -0,0 +1,34 @@
require 'rubygems'
Gem::Specification.new do |spec|
spec.name = 'interface'
spec.version = '1.0.5'
spec.author = 'Daniel J. Berger'
spec.license = 'Artistic-2.0'
spec.email = 'djberg96@gmail.com'
spec.homepage = 'http://github.com/djberg96/interface'
spec.summary = 'Java style interfaces for Ruby'
spec.test_file = 'test/test_interface.rb'
spec.files = Dir['**/*'].reject{ |f| f.include?('git') }
spec.cert_chain = Dir['certs/*']
spec.extra_rdoc_files = ['README', 'CHANGES', 'MANIFEST']
spec.add_development_dependency('test-unit')
spec.add_development_dependency('rake')
spec.metadata = {
'homepage_uri' => 'https://github.com/djberg96/interface',
'bug_tracker_uri' => 'https://github.com/djberg96/interface/issues',
'changelog_uri' => 'https://github.com/djberg96/interface/blob/master/CHANGES',
'documentation_uri' => 'https://github.com/djberg96/interface/wiki',
'source_code_uri' => 'https://github.com/djberg96/interface',
'wiki_uri' => 'https://github.com/djberg96/interface/wiki'
}
spec.description = <<-EOF
The interface library implements Java style interfaces for Ruby.
It lets you define a set a methods that must be defined in the
including class or module, or an error is raised.
EOF
end

View File

@@ -0,0 +1,106 @@
# A module for implementing Java style interfaces in Ruby. For more information
# about Java interfaces, please see:
#
# http://java.sun.com/docs/books/tutorial/java/concepts/interface.html
#
module Interface
# The version of the interface library.
Interface::VERSION = '1.0.5'.freeze
# Raised if a class or instance does not meet the interface requirements.
class MethodMissing < RuntimeError; end
alias :extends :extend
private
def extend_object(obj)
return append_features(obj) if Interface === obj
append_features(class << obj; self end)
included(obj)
end
def append_features(mod)
return super if Interface === mod
# Is this a sub-interface?
inherited = (self.ancestors-[self]).select{ |x| Interface === x }
inherited = inherited.map{ |x| x.instance_variable_get('@ids') }
# Store required method ids
ids = @ids + inherited.flatten
@unreq ||= []
# Iterate over the methods, minus the unrequired methods, and raise
# an error if the method has not been defined.
(ids - @unreq).uniq.each do |id|
unless mod.instance_methods(true).include?(id)
raise Interface::MethodMissing, id
end
end
super mod
end
public
# Accepts an array of method names that define the interface. When this
# module is included/implemented, those method names must have already been
# defined.
#
def required_methods(*ids)
@ids = ids
end
# Accepts an array of method names that are removed as a requirement for
# implementation. Presumably you would use this in a sub-interface where
# you only wanted a partial implementation of an existing interface.
#
def unrequired_methods(*ids)
@unreq ||= []
@unreq += ids
end
end
class Object
# The interface method creates an interface module which typically sets
# a list of methods that must be defined in the including class or module.
# If the methods are not defined, an Interface::MethodMissing error is raised.
#
# A interface can extend an existing interface as well. These are called
# sub-interfaces, and they can included the rules for their parent interface
# by simply extending it.
#
# Example:
#
# # Require 'alpha' and 'beta' methods
# AlphaInterface = interface{
# required_methods :alpha, :beta
# }
#
# # A sub-interface that requires 'beta' and 'gamma' only
# GammaInterface = interface{
# extends AlphaInterface
# required_methods :gamma
# unrequired_methods :alpha
# }
#
# # Raises an Interface::MethodMissing error because :beta is not defined.
# class MyClass
# def alpha
# # ...
# end
# implements AlphaInterface
# end
#
def interface(&block)
Module.new do |mod|
mod.extend(Interface)
mod.instance_eval(&block)
end
end
end
class Module
alias :implements :include
end

View File

@@ -0,0 +1,64 @@
#####################################################
# test_interface.rb
#
# Test suite for the Interface module.
#####################################################
require 'test-unit'
require 'interface'
class TC_Interface < Test::Unit::TestCase
def self.startup
alpha_interface = interface{
required_methods :alpha, :beta
}
gamma_interface = interface{
extends alpha_interface
required_methods :gamma
unrequired_methods :alpha
}
# Workaround for 1.9.x
@@alpha_interface = alpha_interface
@@gamma_interface = gamma_interface
eval("class A; end")
eval("
class B
def alpha; end
def beta; end
end
")
eval("
class C
def beta; end
def gamma; end
end
")
end
def test_version
assert_equal('1.0.5', Interface::VERSION)
assert_true(Interface::VERSION.frozen?)
end
def test_interface_requirements_not_met
assert_raise(Interface::MethodMissing){ A.extend(@@alpha_interface) }
assert_raise(Interface::MethodMissing){ A.new.extend(@@alpha_interface) }
end
def test_sub_interface_requirements_not_met
assert_raise(Interface::MethodMissing){ B.extend(@@gamma_interface) }
assert_raise(Interface::MethodMissing){ B.new.extend(@@gamma_interface) }
end
def test_alpha_interface_requirements_met
assert_nothing_raised{ B.new.extend(@@alpha_interface) }
end
def test_gamma_interface_requirements_met
assert_nothing_raised{ C.new.extend(@@gamma_interface) }
end
end

View File

@@ -0,0 +1,11 @@
source "https://rubygems.org"
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gemspec
group :development do
gem "bundler"
gem "rake"
gem "test-unit"
end

View File

@@ -0,0 +1,22 @@
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.

View File

@@ -0,0 +1,97 @@
# Shell
Shell implements an idiomatic Ruby interface for common UNIX shell commands.
It provides users the ability to execute commands with filters and pipes, like +sh+/+csh+ by using native facilities of Ruby.
## Installation
Add this line to your application's Gemfile:
```ruby
gem 'shell'
```
And then execute:
$ bundle
Or install it yourself as:
$ gem install shell
## Usage
### Temp file creation
In this example we will create three +tmpFile+'s in three different folders under the +/tmp+ directory.
```
sh = Shell.cd("/tmp") # Change to the /tmp directory
sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1")
# make the 'shell-test-1' directory if it doesn't already exist
sh.cd("shell-test-1") # Change to the /tmp/shell-test-1 directory
for dir in ["dir1", "dir3", "dir5"]
if !sh.exists?(dir)
sh.mkdir dir # make dir if it doesn't already exist
sh.cd(dir) do
# change to the `dir` directory
f = sh.open("tmpFile", "w") # open a new file in write mode
f.print "TEST\n" # write to the file
f.close # close the file handler
end
print sh.pwd # output the process working directory
end
end
```
### Temp file creation with self
This example is identical to the first, except we're using CommandProcessor#transact.
CommandProcessor#transact executes the given block against self, in this case +sh+; our Shell object. Within the block we can substitute +sh.cd+ to +cd+, because the scope within the block uses +sh+ already.
```
sh = Shell.cd("/tmp")
sh.transact do
mkdir "shell-test-1" unless exists?("shell-test-1")
cd("shell-test-1")
for dir in ["dir1", "dir3", "dir5"]
if !exists?(dir)
mkdir dir
cd(dir) do
f = open("tmpFile", "w")
f.print "TEST\n"
f.close
end
print pwd
end
end
end
```
### Pipe /etc/printcap into a file
In this example we will read the operating system file +/etc/printcap+, generated by +cupsd+, and then output it to a new file relative to the +pwd+ of +sh+.
```
sh = Shell.new
sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2"
(sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12"
sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2"
(sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12"
```
## Development
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
## Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/shell.
## License
The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).

Some files were not shown because too many files have changed in this diff Show More