663 lines
24 KiB
Bash
Executable file
663 lines
24 KiB
Bash
Executable file
#!/bin/bash
|
||
# PITOOLSV2 — простой SSH-оркестратор:
|
||
# pinstall — создать файл/директорию с правами
|
||
# piproject — собрать проект по .prj
|
||
# deploypi — деплой одного .prj на один хост
|
||
# multideploypi — деплой нескольких блоков MLT+PRJ/DR/FL из одного .prj
|
||
|
||
# ------------------------- pinstall --------------------------
|
||
# pinstall [-h|--here] [-u|--user] [-s|--script] FILE...
|
||
# Создаёт файлы/каталоги с умными правами и владельцем.
|
||
pinstall() {
|
||
local mode=644 owner="$USER" group create_dir=0
|
||
|
||
# Получаем группу текущего пользователя
|
||
group="$(id -gn "$USER" 2>/dev/null || id -gn 2>/dev/null || whoami 2>/dev/null || echo "$USER")"
|
||
|
||
# Парсим флаги
|
||
while [ $# -gt 0 ] && [ "${1#-}" != "$1" ]; do
|
||
case "$1" in
|
||
-h|--here)
|
||
# Наследуем права и владельца от текущей директории
|
||
if [ -d . ]; then
|
||
mode="$(stat -c '%a' . 2>/dev/null || echo 644)"
|
||
owner="$(stat -c '%U' . 2>/dev/null || echo "$USER")"
|
||
group="$(stat -c '%G' . 2>/dev/null || echo "$group")"
|
||
fi
|
||
shift
|
||
;;
|
||
-u|--user)
|
||
# Стандартные права для пользовательских файлов
|
||
mode=644
|
||
owner="$USER"
|
||
group="$(id -gn "$USER" 2>/dev/null || id -gn 2>/dev/null || whoami 2>/dev/null || echo "$USER")"
|
||
shift
|
||
;;
|
||
-s|--script)
|
||
# Принудительно исполняемые права
|
||
mode=755
|
||
shift
|
||
;;
|
||
-d|--directory)
|
||
# Создавать директорию
|
||
create_dir=1
|
||
shift
|
||
;;
|
||
--)
|
||
# Конец флагов
|
||
shift
|
||
break
|
||
;;
|
||
-*)
|
||
echo "Использование: pinstall [-h|--here] [-u|--user] [-s|--script] [-d|--directory] ФАЙЛ..." >&2
|
||
return 1
|
||
;;
|
||
*)
|
||
# Не флаг - выходим из цикла
|
||
break
|
||
;;
|
||
esac
|
||
done
|
||
|
||
# Проверка: хотя бы один файл должен быть указан
|
||
[ $# -eq 0 ] && {
|
||
echo "Использование: pinstall [-h|--here] [-u|--user] [-s|--script] [-d|--directory] ФАЙЛ..." >&2
|
||
return 1
|
||
}
|
||
|
||
# Счётчик созданных объектов
|
||
local created=0
|
||
|
||
# Обрабатываем все переданные файлы
|
||
for f in "$@"; do
|
||
local eff_mode="$mode"
|
||
|
||
# Автоматически делаем скрипты исполняемыми
|
||
case "$(basename "$f")" in
|
||
*.sh|*.py|*.pl|*.rb|*.go|*.js|Makefile|makefile|*.mk)
|
||
eff_mode=755
|
||
;;
|
||
esac
|
||
|
||
# Убираем возможный / в конце для проверки существования
|
||
local check_path="$f"
|
||
[[ "$check_path" == */ ]] && check_path="${check_path%/}"
|
||
|
||
# Проверяем, существует ли уже
|
||
if [ -e "$check_path" ]; then
|
||
# Существует — обновляем права если нужно
|
||
if [ -d "$check_path" ]; then
|
||
# Это директория
|
||
if [ "$eff_mode" != "644" ] && [ "$eff_mode" != "755" ]; then
|
||
chmod "$eff_mode" "$check_path" 2>/dev/null && \
|
||
echo " 🔧 Обновлены права директории: $f" >&2
|
||
fi
|
||
else
|
||
# Это файл
|
||
if [ "$eff_mode" != "644" ]; then
|
||
chmod "$eff_mode" "$check_path" 2>/dev/null && \
|
||
echo " 🔧 Обновлены права файла: $f" >&2
|
||
fi
|
||
fi
|
||
continue # Уже существует, пропускаем создание
|
||
fi
|
||
|
||
# Определяем, создавать директорию или файл
|
||
local is_dir="$create_dir"
|
||
[ "$is_dir" -eq 0 ] && [[ "$f" == */ ]] && is_dir=1
|
||
|
||
if [ "$is_dir" -eq 1 ]; then
|
||
# Создаём директорию
|
||
if install -d -m "$eff_mode" -o "$owner" -g "$group" "$f" 2>/dev/null; then
|
||
echo " 📂 Создана директория: ${f%/}" >&2
|
||
created=$((created + 1))
|
||
else
|
||
echo " ⚠️ Не удалось создать директорию: $f" >&2
|
||
fi
|
||
else
|
||
# Создаём файл
|
||
if install -D -m "$eff_mode" -o "$owner" -g "$group" \
|
||
--backup=numbered /dev/null "$f" 2>/dev/null; then
|
||
# Проверяем, был ли авто-режим 755
|
||
case "$(basename "$f")" in
|
||
*.sh|*.py|*.pl|*.rb|*.go|*.js|Makefile|makefile|*.mk)
|
||
echo " 🔥 AUTO 755 → $f" >&2
|
||
;;
|
||
*)
|
||
echo " 📄 Создан файл: $f" >&2
|
||
;;
|
||
esac
|
||
created=$((created + 1))
|
||
else
|
||
echo " ⚠️ Не удалось создать файл: $f" >&2
|
||
fi
|
||
fi
|
||
done
|
||
|
||
[ "$created" -gt 0 ] && echo "✅ Создано объектов: $created" >&2
|
||
return 0
|
||
}
|
||
|
||
# ------------------------ piproject --------------------------
|
||
# piproject SPEC.prj
|
||
# Читает PRJ/DR/FL и создаёт структуру проекта локально.
|
||
piproject() {
|
||
local spec="$1" root="" curdir="" line="" created_projects=0
|
||
|
||
# Проверка аргументов
|
||
[ -z "$spec" ] && {
|
||
echo "Использование: piproject ФАЙЛ.prj" >&2
|
||
echo "Пример: piproject мойпроект.prj" >&2
|
||
return 1
|
||
}
|
||
|
||
[ ! -f "$spec" ] && {
|
||
echo "❌ Файл спецификации не найден: $spec" >&2
|
||
return 1
|
||
}
|
||
|
||
echo "🌳 Читаем спецификацию: $spec"
|
||
|
||
# Проверяем, есть ли хоть одна PRJ: строка
|
||
if ! grep -q "^PRJ:" "$spec" 2>/dev/null; then
|
||
echo "❌ В файле нет PRJ: определения" >&2
|
||
return 1
|
||
fi
|
||
|
||
# Читаем файл построчно
|
||
while IFS= read -r line || [ -n "$line" ]; do
|
||
# Убираем пробелы в начале и конце
|
||
line="${line#"${line%%[![:space:]]*}"}"
|
||
line="${line%"${line##*[![:space:]]}"}"
|
||
|
||
# Пропускаем пустые строки и комментарии
|
||
case "$line" in
|
||
""|"#"*)
|
||
continue
|
||
;;
|
||
|
||
PRJ:*)
|
||
# Начало нового проекта - определяем корневую директорию
|
||
root="${line#PRJ:}"
|
||
root="${root#"${root%%[![:space:]]*}"}"
|
||
root="${root%"${root##*[![:space:]]}"}"
|
||
|
||
# Проверяем безопасность пути
|
||
if [[ "$root" == *".."* ]] || [[ "$root" == /* ]]; then
|
||
echo "⚠️ Предупреждение: путь '$root' может быть небезопасен" >&2
|
||
fi
|
||
|
||
# Создаём корневую директорию
|
||
echo "📁 Создаём проект: $root/"
|
||
if pinstall -d "$root/"; then
|
||
curdir="$root"
|
||
created_projects=$((created_projects + 1))
|
||
else
|
||
echo "❌ Не удалось создать корень проекта: $root" >&2
|
||
return 1
|
||
fi
|
||
;;
|
||
|
||
DR:*)
|
||
# Создание поддиректории
|
||
[ -z "$root" ] && {
|
||
echo "❌ Сначала определите PRJ: в файле $spec" >&2
|
||
return 1
|
||
}
|
||
|
||
local dir_path="${line#DR:}"
|
||
dir_path="${dir_path#"${dir_path%%[![:space:]]*}"}"
|
||
dir_path="${dir_path%"${dir_path##*[![:space:]]}"}"
|
||
|
||
# Защита от небезопасных путей
|
||
if [[ "$dir_path" == *".."* ]] || [[ "$dir_path" == /* ]]; then
|
||
echo "⚠️ Предупреждение: путь '$dir_path' может быть небезопасен" >&2
|
||
fi
|
||
|
||
# Создаём поддиректорию
|
||
if [ -n "$dir_path" ]; then
|
||
curdir="$root/$dir_path"
|
||
if pinstall -d "$curdir/"; then
|
||
echo " 📂 Директория: $dir_path"
|
||
else
|
||
echo " ⚠️ Не удалось создать директорию: $dir_path" >&2
|
||
fi
|
||
fi
|
||
;;
|
||
|
||
FL:*)
|
||
# Создание файла
|
||
[ -z "$root" ] && {
|
||
echo "❌ Сначала определите PRJ: в файле $spec" >&2
|
||
return 1
|
||
}
|
||
|
||
local file_path="${line#FL:}"
|
||
file_path="${file_path#"${file_path%%[![:space:]]*}"}"
|
||
file_path="${file_path%"${file_path##*[![:space:]]}"}"
|
||
|
||
if [ -z "$file_path" ]; then
|
||
echo "⚠️ Пустое имя файла в FL:, пропускаем" >&2
|
||
continue
|
||
fi
|
||
|
||
# Определяем полный путь к файлу
|
||
local full_path=""
|
||
if [[ "$file_path" == */* ]]; then
|
||
# В пути есть слеш - создаём относительно корня
|
||
full_path="$root/$file_path"
|
||
|
||
# Создаём родительские директории если нужно
|
||
local parent_dir="${full_path%/*}"
|
||
if [ -n "$parent_dir" ] && [ ! -d "$parent_dir" ]; then
|
||
pinstall -d "$parent_dir/" >/dev/null 2>&1
|
||
fi
|
||
else
|
||
# Простое имя файла - создаём в текущей директории
|
||
[ -z "$curdir" ] && curdir="$root"
|
||
full_path="$curdir/$file_path"
|
||
fi
|
||
|
||
# Создаём файл
|
||
if pinstall "$full_path"; then
|
||
echo " 📄 Файл: $file_path"
|
||
else
|
||
echo " ⚠️ Не удалось создать файл: $file_path" >&2
|
||
fi
|
||
;;
|
||
|
||
*)
|
||
# Неизвестная строка
|
||
echo "⚠️ Неизвестная строка в $spec (пропускаем): $line" >&2
|
||
;;
|
||
esac
|
||
done < "$spec"
|
||
|
||
if [ "$created_projects" -gt 0 ]; then
|
||
echo "✅ Готово! Создано проектов: $created_projects"
|
||
else
|
||
echo "ℹ️ Ничего не создано (всё уже существует?)"
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
# ------------------------ deploypi ---------------------------
|
||
# deploypi ХОСТ ПОЛЬЗОВАТЕЛЬ SPEC.prj
|
||
# Копирует pitoolsv2 + spec на хост и запускает piproject.
|
||
deploypi() {
|
||
local host="$1" user="$2" spec="$3"
|
||
|
||
# Проверка аргументов
|
||
[ -z "$host" ] || [ -z "$user" ] || [ -z "$spec" ] && {
|
||
echo "Использование: deploypi ХОСТ ПОЛЬЗОВАТЕЛЬ ФАЙЛ.prj" >&2
|
||
echo "Пример: deploypi server.ru vasya мойпроект.prj" >&2
|
||
return 1
|
||
}
|
||
|
||
[ ! -f "$spec" ] && {
|
||
echo "❌ Файл спецификации не найден: $spec" >&2
|
||
return 1
|
||
}
|
||
|
||
echo "🚀 DEPLOYpi: $spec → $user@$host"
|
||
|
||
# Определяем путь к текущему скрипту
|
||
local self=""
|
||
if [ -f "$0" ]; then
|
||
self="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
|
||
elif [ -n "${BASH_SOURCE[0]}" ]; then
|
||
self="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/$(basename "${BASH_SOURCE[0]}")"
|
||
else
|
||
self="./pitoolsv2.sh"
|
||
fi
|
||
|
||
# Безопасное получение имени спецификации
|
||
local spec_basename="$(basename "$spec")"
|
||
spec_basename="${spec_basename//[!a-zA-Zа-яА-ЯёЁ0-9._-]/_}"
|
||
|
||
echo "🔍 Проверяем соединение с $host..."
|
||
|
||
# Проверяем доступность SSH
|
||
if ! ssh -o ConnectTimeout=5 -o BatchMode=yes -o StrictHostKeyChecking=accept-new \
|
||
"$user@$host" "exit 0" 2>/dev/null; then
|
||
echo "❌ Не могу подключиться к $user@$host через SSH" >&2
|
||
echo " Проверьте: ssh $user@$host" >&2
|
||
return 1
|
||
fi
|
||
|
||
echo "📤 Загружаем инструменты и спецификацию..."
|
||
|
||
# 1. Копируем сам скрипт на удалённый хост
|
||
if ! scp -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new \
|
||
"$self" "$user@$host:~/.pitoolsv2.sh" 2>/dev/null; then
|
||
echo "❌ Не удалось загрузить pitoolsv2 на $host" >&2
|
||
return 1
|
||
fi
|
||
|
||
# 2. Копируем спецификацию проекта
|
||
if ! scp -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new \
|
||
"$spec" "$user@$host:~/$spec_basename" 2>/dev/null; then
|
||
echo "❌ Не удалось загрузить спецификацию на $host" >&2
|
||
return 1
|
||
fi
|
||
|
||
echo "⚡ Выполняем удалённо..."
|
||
|
||
# 3. Запускаем создание проекта на удалённом хосте
|
||
ssh -o ConnectTimeout=30 -o StrictHostKeyChecking=accept-new "$user@$host" "
|
||
echo '🔍 Проверяем загруженные файлы...'
|
||
|
||
if [ ! -f ~/.pitoolsv2.sh ]; then
|
||
echo '❌ Ошибка: pitoolsv2 не найден' >&2
|
||
exit 1
|
||
fi
|
||
|
||
if [ ! -f ~/'$spec_basename' ]; then
|
||
echo '❌ Ошибка: спецификация не найдена' >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo '⚙️ Настраиваем окружение...'
|
||
# Добавляем загрузку pitools в .bashrc если ещё нет
|
||
if ! grep -q 'pitoolsv2' ~/.bashrc 2>/dev/null; then
|
||
echo '[ -f ~/.pitoolsv2.sh ] && . ~/.pitoolsv2.sh # PITOOLSv2' >> ~/.bashrc
|
||
echo ' ✅ Добавили в .bashrc'
|
||
fi
|
||
|
||
# Загружаем скрипт и выполняем
|
||
. ~/.pitoolsv2.sh 2>/dev/null || {
|
||
echo '❌ Не удалось загрузить pitoolsv2' >&2
|
||
exit 1
|
||
}
|
||
|
||
cd ~ || { echo '❌ Не могу перейти в домашнюю директорию' >&2; exit 1; }
|
||
echo '🛠️ Запускаем создание проекта...'
|
||
|
||
if piproject '$spec_basename'; then
|
||
echo '✅ Удалённый проект успешно создан!'
|
||
echo ''
|
||
echo 'Созданные файлы:'
|
||
find . -type f -name '*$spec_basename*' -o -path './*' | head -10
|
||
exit 0
|
||
else
|
||
echo '❌ Ошибка при создании проекта' >&2
|
||
exit 1
|
||
fi
|
||
" 2>&1
|
||
|
||
local result=$?
|
||
if [ $result -eq 0 ]; then
|
||
echo "✅ $host: проект '$spec_basename' успешно развёрнут!"
|
||
return 0
|
||
else
|
||
echo "❌ Ошибка выполнения на $host" >&2
|
||
return $result
|
||
fi
|
||
}
|
||
|
||
# ---------------------- multideploypi ------------------------
|
||
# multideploypi INFRA.prj
|
||
# Читает файл, разбивает на блоки:
|
||
# MLT:host1,host2
|
||
# PRJ/DR/FL...
|
||
# Каждый блок деплоит на свои хосты через deploypi.
|
||
multideploypi() {
|
||
local spec="$1"
|
||
|
||
# Проверка аргументов
|
||
[ -z "$spec" ] && {
|
||
echo "Использование: multideploypi ФАЙЛ_МУЛЬТИ.prj" >&2
|
||
echo "Пример: multideploypi инфраструктура.prj" >&2
|
||
return 1
|
||
}
|
||
|
||
[ ! -f "$spec" ] && {
|
||
echo "❌ Файл спецификации не найден: $spec" >&2
|
||
return 1
|
||
}
|
||
|
||
echo "🌍 MULTIDEPLOYpi: обрабатываем $spec"
|
||
|
||
local line current_hosts="" tmpdir block_spec prj_seen=0
|
||
local block_counter=0
|
||
local pids=""
|
||
local temp_files=""
|
||
|
||
# Создаём временную директорию
|
||
tmpdir="$(mktemp -d -t pitools-XXXXXX 2>/dev/null)" || {
|
||
echo "❌ Не удалось создать временную директорию" >&2
|
||
return 1
|
||
}
|
||
|
||
# Функция для очистки временных файлов
|
||
cleanup() {
|
||
for pid in $pids; do
|
||
kill "$pid" 2>/dev/null || true
|
||
done
|
||
rm -rf "$tmpdir" 2>/dev/null || true
|
||
}
|
||
|
||
# Устанавливаем обработчик прерывания
|
||
trap cleanup EXIT INT TERM
|
||
|
||
# Завершение текущего блока
|
||
finish_block() {
|
||
local hosts="$1" specfile="$2"
|
||
|
||
[ -z "$hosts" ] && return 0
|
||
[ ! -s "$specfile" ] && return 0
|
||
[ "$prj_seen" -eq 0 ] && {
|
||
echo "⚠️ Блок без PRJ: директивы, пропускаем" >&2
|
||
return 0
|
||
}
|
||
|
||
# Разбиваем хосты по запятым
|
||
local hosts_arr
|
||
IFS=',' read -r -a hosts_arr <<< "$hosts"
|
||
|
||
local valid_hosts=0
|
||
for h in "${hosts_arr[@]}"; do
|
||
h="${h#"${h%%[![:space:]]*}"}"
|
||
h="${h%"${h##*[![:space:]]}"}"
|
||
[ -z "$h" ] && continue
|
||
valid_hosts=$((valid_hosts + 1))
|
||
done
|
||
|
||
if [ "$valid_hosts" -eq 0 ]; then
|
||
echo "⚠️ В блоке нет валидных хостов, пропускаем" >&2
|
||
return 0
|
||
fi
|
||
|
||
echo "🔧 Блок $block_counter → $valid_hosts хост(ов): ${hosts_arr[*]}"
|
||
|
||
# Запускаем деплой на каждый хост
|
||
for h in "${hosts_arr[@]}"; do
|
||
h="${h#"${h%%[![:space:]]*}"}"
|
||
h="${h%"${h##*[![:space:]]}"}"
|
||
[ -z "$h" ] && continue
|
||
|
||
# Создаём копию спецификации для каждого хоста
|
||
local host_spec=""
|
||
host_spec="$(mktemp "$tmpdir/spec_${h}_XXXXXX.prj" 2>/dev/null)" || continue
|
||
temp_files="$temp_files $host_spec"
|
||
cp "$specfile" "$host_spec"
|
||
|
||
# Запускаем деплой в фоне
|
||
(
|
||
echo " 🚀 Начинаем деплой на $h..."
|
||
if deploypi "$h" "$USER" "$host_spec" > "$tmpdir/deploy_${h}.log" 2>&1; then
|
||
echo " ✅ $h: деплой успешен"
|
||
else
|
||
echo " ❌ $h: деплой не удался (лог: $tmpdir/deploy_${h}.log)" >&2
|
||
fi
|
||
) &
|
||
pids="$pids $!"
|
||
done
|
||
}
|
||
|
||
# Инициализируем первый блок
|
||
block_counter=1
|
||
block_spec="$(mktemp "$tmpdir/block_${block_counter}_XXXXXX.prj" 2>/dev/null)" || {
|
||
echo "❌ Не удалось создать временный файл" >&2
|
||
return 1
|
||
}
|
||
temp_files="$temp_files $block_spec"
|
||
|
||
echo "📖 Парсим спецификацию..."
|
||
|
||
# Читаем файл построчно
|
||
while IFS= read -r line || [ -n "$line" ]; do
|
||
# Убираем лишние пробелы
|
||
line="${line#"${line%%[![:space:]]*}"}"
|
||
line="${line%"${line##*[![:space:]]}"}"
|
||
|
||
case "$line" in
|
||
""|"#"*)
|
||
# Комментарии и пустые строки сохраняем для читаемости
|
||
[ -n "$block_spec" ] && echo "$line" >> "$block_spec"
|
||
;;
|
||
|
||
MLT:*)
|
||
# Новый блок хостов
|
||
echo "📦 Нашли MLT блок: ${line#MLT:}"
|
||
|
||
# Завершаем предыдущий блок
|
||
finish_block "$current_hosts" "$block_spec"
|
||
|
||
# Начинаем новый блок
|
||
current_hosts="${line#MLT:}"
|
||
block_counter=$((block_counter + 1))
|
||
block_spec="$(mktemp "$tmpdir/block_${block_counter}_XXXXXX.prj" 2>/dev/null)" || {
|
||
echo "❌ Не удалось создать временный файл для блока $block_counter" >&2
|
||
return 1
|
||
}
|
||
temp_files="$temp_files $block_spec"
|
||
prj_seen=0
|
||
|
||
# Сохраняем MLT строку в новый блок
|
||
echo "$line" >> "$block_spec"
|
||
;;
|
||
|
||
PRJ:*)
|
||
# Начало описания проекта
|
||
echo "$line" >> "$block_spec"
|
||
prj_seen=1
|
||
;;
|
||
|
||
DR:*|FL:*)
|
||
# Описание директорий и файлов
|
||
[ -z "$block_spec" ] && {
|
||
echo "❌ DR: или FL: без MLT: блока" >&2
|
||
return 1
|
||
}
|
||
echo "$line" >> "$block_spec"
|
||
;;
|
||
|
||
*)
|
||
# Неизвестные строки пропускаем с предупреждением
|
||
echo "⚠️ Неизвестная директива, пропускаем: $line" >&2
|
||
;;
|
||
esac
|
||
done < "$spec"
|
||
|
||
# Завершаем последний блок
|
||
finish_block "$current_hosts" "$block_spec"
|
||
|
||
# Ждём завершения всех фоновых процессов
|
||
if [ -n "$pids" ]; then
|
||
echo "⏳ Ждём завершения всех деплоев..."
|
||
local failed=0
|
||
for pid in $pids; do
|
||
if wait "$pid"; then
|
||
echo "✓ Процесс $pid завершился успешно"
|
||
else
|
||
echo "✗ Процесс $pid завершился с ошибкой" >&2
|
||
failed=1
|
||
fi
|
||
done
|
||
|
||
if [ "$failed" -eq 1 ]; then
|
||
echo "⚠️ Некоторые деплои не удались. Логи в: $tmpdir"
|
||
echo " Посмотреть: ls -la $tmpdir/*.log"
|
||
# Не удаляем временную директорию при ошибках
|
||
trap - EXIT INT TERM
|
||
return 1
|
||
else
|
||
echo "✅ Все деплои успешно завершены!"
|
||
return 0
|
||
fi
|
||
else
|
||
echo "ℹ️ Нет хостов для деплоя"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# -------------------------- help -----------------------------
|
||
# Короткая подсказка по доступным командам.
|
||
pitools_help() {
|
||
cat <<EOF
|
||
PITOOLSv2 — Простой SSH-оркестратор для всех
|
||
===========================================
|
||
|
||
Доступные команды:
|
||
pinstall [-h|-u|-s|-d] ФАЙЛ... Создать файлы/директории
|
||
-h, --here Унаследовать права от текущей папки
|
||
-u, --user Стандартные права пользователя (644)
|
||
-s, --script Исполняемые права (755)
|
||
-d, --directory Создать директорию (не файл)
|
||
.sh, .py, .js файлы автоматически получают 755!
|
||
|
||
piproject ФАЙЛ.prj Создать структуру проекта
|
||
Формат:
|
||
PRJ:имя_проекта # Корень проекта
|
||
DR:подпапка # Создать папку
|
||
FL:файл # Создать файл
|
||
FL:путь/к/файлу # Файл с путём
|
||
# Комментарии разрешены
|
||
|
||
deploypi ХОСТ ПОЛЬЗОВАТЕЛЬ ФАЙЛ.prj Деплой на один хост
|
||
Пример: deploypi server.ru vasya проект.prj
|
||
|
||
multideploypi ФАЙЛ_МУЛЬТИ.prj Деплой на несколько хостов
|
||
Формат:
|
||
MLT:хост1,хост2,хост3 # Хосты для этого блока
|
||
PRJ:проект # Описание проекта
|
||
DR:... # Папки
|
||
FL:... # Файлы
|
||
|
||
pitools_help Показать эту справку
|
||
|
||
Примеры:
|
||
pinstall script.sh # Создаёт script.sh с правами 755
|
||
piproject мойпроект.prj # Создать локальный проект
|
||
deploypi server1 vasya app.prj # Деплой на один сервер
|
||
multideploypi infra.prj # Деплой на несколько серверов
|
||
|
||
Советы:
|
||
- Если файл/папка уже существует, права будут обновлены
|
||
- Ошибки не останавливают выполнение (только предупреждения)
|
||
- Все пути безопасно обрабатываются
|
||
EOF
|
||
}
|
||
|
||
# Автоматическое выполнение команды если скрипт вызван напрямую
|
||
if [ "$0" = "${BASH_SOURCE[0]:-$0}" ]; then
|
||
case "${1:-}" in
|
||
pinstall|piproject|deploypi|multideploypi|pitools_help)
|
||
"$@"
|
||
;;
|
||
"")
|
||
echo "PITOOLSv2 загружен успешно!"
|
||
echo "Используйте 'pitools_help' для справки."
|
||
echo ""
|
||
echo "Быстрый старт:"
|
||
echo " . ./pitoolsv2.sh # Загрузить в текущую сессию"
|
||
echo " piproject пример.prj # Создать проект"
|
||
;;
|
||
*)
|
||
echo "❌ Неизвестная команда: $1" >&2
|
||
echo "Используйте: pinstall, piproject, deploypi, multideploypi, pitools_help" >&2
|
||
exit 1
|
||
;;
|
||
esac
|
||
fi
|