Files
balikci/deploy.sh

643 lines
23 KiB
Bash
Raw Normal View History

2025-11-10 20:01:41 +03:00
#!/bin/bash
###############################################################################
# Oltalama Test Yönetim Paneli - Otomatik Kurulum Scripti
# Version: 1.0.0
# Date: 2025-11-10
###############################################################################
set -e # Exit on error
# Renkli çıktılar
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Değişkenler
INSTALL_DIR="/opt/oltalama"
LOG_DIR="/var/log/oltalama"
BACKUP_DIR="${INSTALL_DIR}/backups"
2025-11-11 04:30:25 +03:00
USER="oltalama" # Tüm sistemler için ortak kullanıcı
2025-11-10 20:01:41 +03:00
NODE_VERSION="20"
# Fonksiyonlar
print_header() {
echo -e "\n${BLUE}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}║ Oltalama Test Yönetim Paneli - Kurulum Scripti ║${NC}"
echo -e "${BLUE}║ Version 1.0.0 ║${NC}"
echo -e "${BLUE}║ ║${NC}"
echo -e "${BLUE}╚═══════════════════════════════════════════════════════════════╝${NC}\n"
}
print_success() {
echo -e "${GREEN}$1${NC}"
}
print_error() {
echo -e "${RED}$1${NC}"
}
print_warning() {
echo -e "${YELLOW}$1${NC}"
}
print_info() {
echo -e "${BLUE} $1${NC}"
}
check_root() {
if [[ $EUID -ne 0 ]]; then
print_error "Bu script root yetkisi ile çalıştırılmalıdır."
print_info "Lütfen 'sudo ./deploy.sh' komutunu kullanın."
exit 1
fi
}
check_os() {
if [[ -f /etc/os-release ]]; then
. /etc/os-release
OS=$ID
VERSION=$VERSION_ID
print_success "İşletim sistemi tespit edildi: $PRETTY_NAME"
2025-11-11 04:30:25 +03:00
# Paket yöneticisi tespit et
if command -v apt-get &> /dev/null; then
PKG_MANAGER="apt"
print_info "Paket yöneticisi: APT (Debian/Ubuntu)"
elif command -v dnf &> /dev/null; then
PKG_MANAGER="dnf"
print_info "Paket yöneticisi: DNF (RedHat/Oracle/Fedora)"
elif command -v yum &> /dev/null; then
PKG_MANAGER="yum"
print_info "Paket yöneticisi: YUM (RedHat/CentOS)"
else
print_error "Desteklenen paket yöneticisi bulunamadı!"
exit 1
fi
2025-11-10 20:01:41 +03:00
else
print_error "İşletim sistemi tespit edilemedi!"
exit 1
fi
}
install_nodejs() {
print_info "Node.js ${NODE_VERSION}.x kuruluyor..."
if command -v node &> /dev/null; then
CURRENT_VERSION=$(node -v | cut -d'v' -f2 | cut -d'.' -f1)
if [[ $CURRENT_VERSION -ge $NODE_VERSION ]]; then
print_success "Node.js $(node -v) zaten yüklü."
return
fi
fi
# NodeSource repository ekle
2025-11-11 04:30:25 +03:00
if [[ "$PKG_MANAGER" == "apt" ]]; then
curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash -
apt-get install -y nodejs
elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then
curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash -
$PKG_MANAGER install -y nodejs
fi
2025-11-10 20:01:41 +03:00
print_success "Node.js $(node -v) kuruldu."
print_success "npm $(npm -v) kuruldu."
}
install_dependencies() {
print_info "Sistem bağımlılıkları kuruluyor..."
2025-11-11 04:30:25 +03:00
if [[ "$PKG_MANAGER" == "apt" ]]; then
apt-get update
apt-get install -y git curl wget build-essential sqlite3
elif [[ "$PKG_MANAGER" == "dnf" ]] || [[ "$PKG_MANAGER" == "yum" ]]; then
$PKG_MANAGER update -y
# EPEL repository (bazı paketler için gerekli)
$PKG_MANAGER install -y epel-release 2>/dev/null || true
# Paketleri kur
$PKG_MANAGER install -y git curl wget gcc-c++ make sqlite
# Development tools
$PKG_MANAGER groupinstall -y "Development Tools" 2>/dev/null || true
fi
2025-11-10 20:01:41 +03:00
print_success "Sistem bağımlılıkları kuruldu."
}
install_pm2() {
print_info "PM2 process manager kuruluyor..."
npm install -g pm2
print_success "PM2 $(pm2 -v) kuruldu."
}
setup_directories() {
print_info "Dizinler oluşturuluyor..."
mkdir -p $LOG_DIR
mkdir -p $BACKUP_DIR
mkdir -p "${INSTALL_DIR}/backend/database"
print_success "Dizinler oluşturuldu."
}
2025-11-11 04:30:25 +03:00
create_user() {
print_info "Sistem kullanıcısı kontrol ediliyor..."
if id "$USER" &>/dev/null; then
print_success "Kullanıcı '$USER' zaten mevcut."
else
print_info "Kullanıcı '$USER' oluşturuluyor..."
useradd -r -s /bin/bash -d $INSTALL_DIR -m $USER
print_success "Kullanıcı '$USER' oluşturuldu."
fi
}
2025-11-10 20:01:41 +03:00
install_project() {
print_info "Proje dosyaları kontrol ediliyor..."
# Eğer script zaten proje dizininde çalıştırılıyorsa
if [[ -f "$(pwd)/backend/package.json" ]]; then
CURRENT_DIR=$(pwd)
print_info "Mevcut dizinden kurulum yapılıyor: $CURRENT_DIR"
if [[ "$CURRENT_DIR" != "$INSTALL_DIR" ]]; then
print_info "Dosyalar $INSTALL_DIR dizinine kopyalanıyor..."
# rsync yerine cp kullan (daha yaygın)
# Önce .git ve node_modules hariç tüm dosyaları kopyala
find "$CURRENT_DIR" -mindepth 1 -maxdepth 1 \
! -name 'node_modules' \
! -name '.git' \
! -name 'logs' \
! -name 'database' \
-exec cp -r {} "$INSTALL_DIR/" \;
print_success "Dosyalar kopyalandı."
2025-11-10 20:01:41 +03:00
fi
else
print_error "Proje dosyaları bulunamadı!"
print_info "Script'i proje dizininde çalıştırın veya projeyi klonlayın."
exit 1
fi
print_success "Proje dosyaları hazır."
}
install_backend() {
print_info "Backend dependencies kuruluyor..."
cd "${INSTALL_DIR}/backend"
npm install --production
print_success "Backend dependencies kuruldu."
}
install_frontend() {
print_info "Frontend dependencies kuruluyor..."
cd "${INSTALL_DIR}/frontend"
npm install
print_success "Frontend dependencies kuruldu."
}
setup_env_files() {
print_info "Çevre değişkenleri ayarlanıyor..."
# Backend .env
if [[ ! -f "${INSTALL_DIR}/backend/.env" ]]; then
cp "${INSTALL_DIR}/backend/.env.example" "${INSTALL_DIR}/backend/.env"
# Session secret oluştur
SESSION_SECRET=$(node -e "console.log(require('crypto').randomBytes(64).toString('hex'))")
# .env dosyasını güncelle
sed -i "s|NODE_ENV=development|NODE_ENV=production|g" "${INSTALL_DIR}/backend/.env"
sed -i "s|SESSION_SECRET=.*|SESSION_SECRET=${SESSION_SECRET}|g" "${INSTALL_DIR}/backend/.env"
sed -i "s|DB_PATH=.*|DB_PATH=${INSTALL_DIR}/backend/database/oltalama.db|g" "${INSTALL_DIR}/backend/.env"
print_success "Backend .env dosyası oluşturuldu."
print_warning "Gmail ve Telegram ayarlarını panelden yapabilirsiniz."
else
print_info "Backend .env dosyası zaten mevcut."
fi
# Frontend .env
if [[ ! -f "${INSTALL_DIR}/frontend/.env" ]]; then
cp "${INSTALL_DIR}/frontend/.env.example" "${INSTALL_DIR}/frontend/.env"
print_success "Frontend .env dosyası oluşturuldu."
else
print_info "Frontend .env dosyası zaten mevcut."
fi
}
setup_admin_user() {
print_info "Admin kullanıcısı oluşturuluyor..."
# Check if admin already exists
ADMIN_COUNT=$(sqlite3 "${INSTALL_DIR}/backend/database/oltalama.db" "SELECT COUNT(*) FROM admin_user;" 2>/dev/null || echo "0")
if [[ "$ADMIN_COUNT" -gt 0 ]]; then
print_info "Admin kullanıcısı zaten mevcut, atlanıyor."
return
fi
echo ""
print_warning "╔═══════════════════════════════════════════════════════════════╗"
print_warning "║ Admin Kullanıcı Bilgilerini Oluşturun ║"
print_warning "╚═══════════════════════════════════════════════════════════════╝"
echo ""
# Username
while true; do
read -p "Admin kullanıcı adı (en az 3 karakter): " ADMIN_USERNAME
if [[ ${#ADMIN_USERNAME} -ge 3 ]]; then
break
else
print_error "Kullanıcı adı en az 3 karakter olmalıdır!"
fi
done
# Password with validation
while true; do
read -sp "Admin şifresi (en az 8 karakter, harf ve rakam içermeli): " ADMIN_PASSWORD
echo ""
# Password length check
if [[ ${#ADMIN_PASSWORD} -lt 8 ]]; then
print_error "Şifre en az 8 karakter olmalıdır!"
continue
fi
# Check for letters and numbers
if ! [[ "$ADMIN_PASSWORD" =~ [a-zA-Z] ]] || ! [[ "$ADMIN_PASSWORD" =~ [0-9] ]]; then
print_error "Şifre hem harf hem de rakam içermelidir!"
continue
fi
# Confirm password
read -sp "Şifreyi tekrar girin: " ADMIN_PASSWORD_CONFIRM
echo ""
if [[ "$ADMIN_PASSWORD" == "$ADMIN_PASSWORD_CONFIRM" ]]; then
break
else
print_error "Şifreler eşleşmiyor! Tekrar deneyin."
fi
done
# Create admin user using Node.js
cd "${INSTALL_DIR}/backend"
cat > "${INSTALL_DIR}/backend/create_admin_temp.js" << EOF
2025-11-10 20:01:41 +03:00
const bcrypt = require('bcrypt');
const { sequelize } = require('./src/config/database');
const AdminUser = require('./src/models/AdminUser');
(async () => {
try {
await sequelize.authenticate();
const hashedPassword = await bcrypt.hash('${ADMIN_PASSWORD}', 10);
await AdminUser.create({
username: '${ADMIN_USERNAME}',
password_hash: hashedPassword,
email: null,
full_name: 'Administrator',
});
console.log('✓ Admin kullanıcısı oluşturuldu');
process.exit(0);
} catch (error) {
console.error('✗ Hata:', error.message);
process.exit(1);
}
})();
EOF
cd "${INSTALL_DIR}/backend"
node create_admin_temp.js
rm -f create_admin_temp.js
2025-11-10 20:01:41 +03:00
print_success "Admin kullanıcısı oluşturuldu: ${ADMIN_USERNAME}"
echo ""
}
setup_database() {
print_info "Database oluşturuluyor..."
cd "${INSTALL_DIR}/backend"
# Migrations
node migrations/run-migrations.js
print_success "Database migrations tamamlandı."
# Seed sample data (companies and templates only, not admin user)
ADMIN_COUNT=$(sqlite3 "${INSTALL_DIR}/backend/database/oltalama.db" "SELECT COUNT(*) FROM admin_user;" 2>/dev/null || echo "0")
if [[ "$ADMIN_COUNT" -eq 0 ]]; then
# Seed only non-admin data (create script in backend directory)
cat > "${INSTALL_DIR}/backend/seed_data_temp.js" << 'EOF'
2025-11-10 20:01:41 +03:00
const { sequelize } = require('./src/config/database');
const { Company, MailTemplate } = require('./src/models');
(async () => {
try {
await sequelize.authenticate();
// Seed companies
const companies = [
{ name: 'Türk Telekom', domain: 'turktelekom.com.tr', description: 'Türkiye\'nin lider telekomünikasyon şirketi' },
{ name: 'İş Bankası', domain: 'isbank.com.tr', description: 'Türkiye\'nin en büyük özel sermayeli bankası' },
{ name: 'PTT', domain: 'ptt.gov.tr', description: 'Posta ve Telgraf Teşkilatı' },
];
for (const company of companies) {
await Company.findOrCreate({ where: { name: company.name }, defaults: company });
}
// Seed templates
const templates = [
{
name: 'Banka Güvenlik Uyarısı',
template_type: 'bank',
subject_template: '🔒 {{company_name}} - Hesap Güvenlik Uyarısı',
body_html: '<html><body style="font-family: Arial, sans-serif; line-height: 1.6;"><div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd;"><h2 style="color: #d32f2f;">🔒 Güvenlik Uyarısı</h2><p>Sayın {{employee_name}},</p><p>{{company_name}} hesabınızda şüpheli bir aktivite tespit edildi. Hesabınızın güvenliğini sağlamak için lütfen aşağıdaki bağlantıya tıklayarak kimlik doğrulaması yapın.</p><p style="text-align: center; margin: 30px 0;"><a href="{{tracking_url}}" style="background-color: #d32f2f; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">Hesabımı Doğrula</a></p><p style="color: #666; font-size: 12px;">Bu işlemi 24 saat içinde yapmazsanız hesabınız geçici olarak askıya alınabilir.</p><p style="color: #666; font-size: 12px;">Tarih: {{current_date}}</p><hr style="border: none; border-top: 1px solid #eee; margin: 20px 0;"><p style="color: #999; font-size: 11px;">Bu bir phishing testidir. Gerçek bir güvenlik tehdidi değildir.</p></div></body></html>',
description: 'Banka hesap güvenliği temalı phishing test maili',
active: true,
},
{
name: 'E-Devlet Sistem Güncellemesi',
template_type: 'edevlet',
subject_template: '⚠️ E-Devlet - Sistem Güncellemesi Gerekli',
body_html: '<html><body style="font-family: Arial, sans-serif; line-height: 1.6;"><div style="max-width: 600px; margin: 0 auto; padding: 20px; border: 1px solid #ddd;"><div style="background-color: #c62828; color: white; padding: 15px; text-align: center;"><h2 style="margin: 0;">E-DEVLET KAPISI</h2></div><div style="padding: 20px;"><p>Sayın {{employee_name}},</p><p>E-Devlet sistemimizde önemli bir güvenlik güncellemesi yapılmaktadır. Hesabınıza erişiminizi sürdürebilmek için lütfen kimlik bilgilerinizi güncelleyin.</p><p style="text-align: center; margin: 30px 0;"><a href="{{tracking_url}}" style="background-color: #c62828; color: white; padding: 12px 30px; text-decoration: none; border-radius: 5px; display: inline-block;">Bilgilerimi Güncelle</a></p><p style="background-color: #fff3cd; border-left: 4px solid #ffc107; padding: 10px; color: #856404;">⚠️ Bu işlemi 48 saat içinde tamamlamazsanız E-Devlet hesabınız askıya alınacaktır.</p><p style="color: #666; font-size: 12px;">İşlem Tarihi: {{current_date}}</p></div><div style="background-color: #f5f5f5; padding: 15px; text-align: center; color: #666; font-size: 11px;"><p>Bu bir phishing farkındalık testidir.</p><p>© {{current_year}} E-Devlet Kapısı</p></div></div></body></html>',
description: 'E-Devlet sistem güncellemesi temalı phishing test maili',
active: true,
},
];
for (const template of templates) {
await MailTemplate.findOrCreate({ where: { template_type: template.template_type }, defaults: template });
}
console.log('✓ Örnek veriler oluşturuldu');
process.exit(0);
} catch (error) {
console.error('✗ Hata:', error.message);
process.exit(1);
}
})();
EOF
cd "${INSTALL_DIR}/backend"
node seed_data_temp.js
rm -f seed_data_temp.js
2025-11-10 20:01:41 +03:00
print_success "Örnek veriler oluşturuldu (şirketler ve mail şablonları)."
else
print_info "Database zaten veri içeriyor, seed atlanıyor."
fi
}
build_frontend() {
print_info "Frontend build ediliyor..."
cd "${INSTALL_DIR}/frontend"
npm run build
print_success "Frontend build tamamlandı."
}
setup_pm2() {
print_info "PM2 konfigürasyonu yapılıyor..."
# ecosystem.config.js oluştur
cat > "${INSTALL_DIR}/ecosystem.config.js" << 'EOF'
module.exports = {
apps: [
{
name: 'oltalama-backend',
cwd: '/opt/oltalama/backend',
script: 'src/app.js',
instances: 1,
exec_mode: 'cluster',
watch: false,
max_memory_restart: '500M',
env: {
NODE_ENV: 'production',
PORT: 3000,
},
error_file: '/var/log/oltalama/backend-error.log',
out_file: '/var/log/oltalama/backend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
},
{
name: 'oltalama-frontend',
cwd: '/opt/oltalama/frontend',
script: 'node_modules/.bin/vite',
args: 'preview --host 0.0.0.0 --port 4173',
2025-11-10 20:01:41 +03:00
instances: 1,
exec_mode: 'fork',
watch: false,
max_memory_restart: '300M',
env: {
NODE_ENV: 'production',
PORT: 4173,
},
error_file: '/var/log/oltalama/frontend-error.log',
out_file: '/var/log/oltalama/frontend-out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
},
],
};
EOF
print_success "PM2 konfigürasyon dosyası oluşturuldu."
}
start_services() {
print_info "Servisler başlatılıyor..."
cd "${INSTALL_DIR}"
# PM2 ile başlat
pm2 start ecosystem.config.js
# Startup script oluştur
pm2 startup systemd -u root --hp /root
pm2 save
print_success "Servisler başlatıldı."
# Durum göster
sleep 2
pm2 status
}
setup_permissions() {
print_info "Dosya izinleri ayarlanıyor..."
# Dizin sahipliği
chown -R ${USER}:${USER} ${INSTALL_DIR}
chown -R ${USER}:${USER} ${LOG_DIR}
# .env dosyaları
chmod 600 "${INSTALL_DIR}/backend/.env"
chmod 600 "${INSTALL_DIR}/frontend/.env"
# Database
chmod 600 "${INSTALL_DIR}/backend/database/oltalama.db"
print_success "Dosya izinleri ayarlandı."
}
setup_firewall() {
print_info "Firewall ayarlanıyor..."
if command -v ufw &> /dev/null; then
2025-11-11 04:30:25 +03:00
# Ubuntu/Debian - UFW
print_info "UFW kullanılıyor..."
2025-11-10 20:01:41 +03:00
# SSH izin ver
ufw allow 22/tcp comment 'SSH'
# HTTP/HTTPS izin ver
ufw allow 80/tcp comment 'HTTP'
ufw allow 443/tcp comment 'HTTPS'
# Backend ve Frontend portlarını engelle (sadece localhost'tan erişilebilir)
ufw deny 3000/tcp comment 'Oltalama Backend (use reverse proxy)'
ufw deny 4173/tcp comment 'Oltalama Frontend (use reverse proxy)'
# UFW'yi aktifleştir (sadece henüz aktif değilse)
if ! ufw status | grep -q "Status: active"; then
print_warning "UFW firewall aktifleştiriliyor..."
print_warning "SSH bağlantınız kopmayacak (port 22 açık)."
read -p "Devam etmek için ENTER'a basın..."
echo "y" | ufw enable
fi
2025-11-11 04:30:25 +03:00
print_success "Firewall ayarlandı (UFW)."
elif command -v firewall-cmd &> /dev/null; then
# RedHat/Oracle/CentOS - firewalld
print_info "firewalld kullanılıyor..."
# firewalld'yi başlat ve aktifleştir
systemctl start firewalld 2>/dev/null || true
systemctl enable firewalld 2>/dev/null || true
# HTTP/HTTPS izin ver
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --permanent --add-service=ssh
# Backend ve Frontend portları sadece localhost'tan erişilebilir
# (reverse proxy kullanılacağı için dışarıdan erişim kapalı)
# Yeniden yükle
firewall-cmd --reload
print_success "Firewall ayarlandı (firewalld)."
2025-11-10 20:01:41 +03:00
else
2025-11-11 04:30:25 +03:00
print_warning "Firewall bulunamadı, firewall ayarları atlanıyor."
print_warning "Güvenlik için manuel olarak firewall yapılandırmanız önerilir."
2025-11-10 20:01:41 +03:00
fi
}
setup_backup_cron() {
print_info "Otomatik yedekleme ayarlanıyor..."
# Backup script oluştur
cat > "${INSTALL_DIR}/backup.sh" << 'EOF'
#!/bin/bash
BACKUP_DIR="/opt/oltalama/backups"
DB_PATH="/opt/oltalama/backend/database/oltalama.db"
DATE=$(date +%Y%m%d-%H%M%S)
mkdir -p $BACKUP_DIR
cp $DB_PATH "$BACKUP_DIR/oltalama-$DATE.db"
find $BACKUP_DIR -name "oltalama-*.db" -mtime +30 -delete
echo "Backup completed: oltalama-$DATE.db"
EOF
chmod +x "${INSTALL_DIR}/backup.sh"
# Crontab ekle
CRON_JOB="0 3 * * * ${INSTALL_DIR}/backup.sh >> ${LOG_DIR}/backup.log 2>&1"
(crontab -l 2>/dev/null | grep -v "backup.sh"; echo "$CRON_JOB") | crontab -
print_success "Otomatik yedekleme ayarlandı (her gün saat 03:00)."
}
print_completion() {
echo -e "\n${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}║ 🎉 Kurulum Tamamlandı! 🎉 ║${NC}"
echo -e "${GREEN}║ ║${NC}"
echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}\n"
print_info "Servis Bilgileri:"
echo -e " Backend: ${BLUE}http://localhost:3000${NC}"
echo -e " Frontend: ${BLUE}http://localhost:4173${NC}"
print_info "\nAdmin Hesabı:"
echo -e " ${GREEN}${NC} Kurulum sırasında oluşturuldu"
echo -e " ${GREEN}${NC} Güvenli şifre kullanıldı"
print_info "\nYapılması Gerekenler:"
echo " 1. Nginx Proxy Manager'da reverse proxy ayarları yapın"
echo " 2. Frontend için: yourdomain.com → localhost:4173"
echo " 3. Backend API için path: /api → localhost:3000"
echo " 4. SSL sertifikası ekleyin"
echo " 5. Panele giriş yapın ve Gmail/Telegram ayarlarını yapın"
print_info "\nYararlı Komutlar:"
echo " Servis durumu: pm2 status"
echo " Logları izle: pm2 logs"
echo " Servis yeniden başlat: pm2 restart all"
echo " Servis durdur: pm2 stop all"
print_info "\nDokümantasyon:"
echo " Detaylı kurulum kılavuzu: ${INSTALL_DIR}/DEPLOYMENT.md"
echo " Kullanım kılavuzu: ${INSTALL_DIR}/KULLANIM.md"
echo " Hızlı başlangıç: ${INSTALL_DIR}/QUICKSTART.md"
print_success "\nKurulum başarıyla tamamlandı!"
}
# Ana kurulum fonksiyonu
main() {
print_header
check_root
check_os
print_info "Kurulum başlıyor...\n"
install_dependencies
install_nodejs
install_pm2
2025-11-11 04:30:25 +03:00
create_user
2025-11-10 20:01:41 +03:00
setup_directories
install_project
install_backend
install_frontend
setup_env_files
setup_database
setup_admin_user
build_frontend
setup_pm2
setup_permissions
start_services
setup_firewall
setup_backup_cron
print_completion
}
# Script'i çalıştır
main "$@"