Fix data directory creation issue on clean install
- Added improved data directory handling in RSSFeedManager - Added synchronous creation of data directory in constructor - Created test-and-start.sh script to ensure data directory exists - Updated service module to use the startup script - Added fallback methods for data directory creation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -18,8 +18,31 @@ class RssFeedManager {
|
||||
this.updateIntervalMinutes = config.updateIntervalMinutes || 60;
|
||||
this.parser = new xml2js.Parser({ explicitArray: false });
|
||||
|
||||
// Ensure dataPath is properly defined
|
||||
this.dataPath = path.join(__dirname, '..', 'data');
|
||||
// Set up the data path - first check if a data path was provided in the config
|
||||
if (config.dataPath) {
|
||||
this.dataPath = config.dataPath;
|
||||
} else {
|
||||
// Otherwise, use the default path relative to this module
|
||||
this.dataPath = path.join(__dirname, '..', 'data');
|
||||
|
||||
// Log the data path for debugging
|
||||
console.log(`Data directory path set to: ${this.dataPath}`);
|
||||
|
||||
// Create the data directory synchronously to make sure it exists
|
||||
try {
|
||||
// Check if fs.mkdirSync is available
|
||||
if (fs.mkdirSync) {
|
||||
const fsSync = require('fs');
|
||||
if (!fsSync.existsSync(this.dataPath)) {
|
||||
fsSync.mkdirSync(this.dataPath, { recursive: true });
|
||||
console.log(`Created data directory synchronously: ${this.dataPath}`);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`Warning: Could not create data directory synchronously: ${err.message}`);
|
||||
// Will try again asynchronously in ensureDataDirectory
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum items to keep in memory to prevent memory leaks
|
||||
this.maxItemsInMemory = config.maxItemsInMemory || 5000;
|
||||
@@ -31,6 +54,10 @@ class RssFeedManager {
|
||||
}
|
||||
|
||||
try {
|
||||
// Make sure the data directory exists first
|
||||
await this.ensureDataDirectory();
|
||||
console.log(`Using data directory: ${this.dataPath}`);
|
||||
|
||||
// Load existing feeds and items
|
||||
await this.loadFeeds();
|
||||
await this.loadItems();
|
||||
@@ -482,10 +509,22 @@ class RssFeedManager {
|
||||
|
||||
async ensureDataDirectory() {
|
||||
try {
|
||||
// Create data directory with recursive option (creates all parent directories if they don't exist)
|
||||
await fs.mkdir(this.dataPath, { recursive: true });
|
||||
console.log(`Ensured data directory exists at: ${this.dataPath}`);
|
||||
} catch (error) {
|
||||
console.error('Error creating data directory:', error);
|
||||
throw error;
|
||||
// Log the error details for debugging
|
||||
console.error(`Error creating data directory ${this.dataPath}:`, error);
|
||||
|
||||
// Try an alternate approach if the first method fails
|
||||
try {
|
||||
const { execSync } = require('child_process');
|
||||
execSync(`mkdir -p "${this.dataPath}"`);
|
||||
console.log(`Created data directory using fallback method: ${this.dataPath}`);
|
||||
} catch (fallbackError) {
|
||||
console.error('Fallback method for creating data directory also failed:', fallbackError);
|
||||
throw error; // Throw the original error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
305
modules/service-setup-module-updated.sh
Executable file
305
modules/service-setup-module-updated.sh
Executable file
@@ -0,0 +1,305 @@
|
||||
#!/bin/bash
|
||||
# Service setup module for Transmission RSS Manager Installation
|
||||
|
||||
# Setup systemd service
|
||||
function setup_service() {
|
||||
log "INFO" "Setting up systemd service..."
|
||||
|
||||
# Ensure required variables are set
|
||||
if [ -z "$SERVICE_NAME" ]; then
|
||||
log "ERROR" "SERVICE_NAME variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$USER" ]; then
|
||||
log "ERROR" "USER variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$INSTALL_DIR" ]; then
|
||||
log "ERROR" "INSTALL_DIR variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$CONFIG_DIR" ]; then
|
||||
log "ERROR" "CONFIG_DIR variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$PORT" ]; then
|
||||
log "ERROR" "PORT variable is not set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if systemd is available
|
||||
if ! command -v systemctl &> /dev/null; then
|
||||
log "ERROR" "systemd is not available on this system"
|
||||
log "INFO" "Please set up the service manually using your system's service manager"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Ensure the test-and-start script exists and is executable
|
||||
TEST_START_SCRIPT="$INSTALL_DIR/scripts/test-and-start.sh"
|
||||
mkdir -p "$(dirname "$TEST_START_SCRIPT")"
|
||||
cat > "$TEST_START_SCRIPT" << 'EOF'
|
||||
#!/bin/bash
|
||||
# Script to ensure data directory exists and start the application
|
||||
|
||||
# Define paths
|
||||
APP_DIR="$(dirname "$(dirname "$(readlink -f "$0")")")"
|
||||
DATA_DIR="$APP_DIR/data"
|
||||
|
||||
echo "Starting Transmission RSS Manager..."
|
||||
echo "Application directory: $APP_DIR"
|
||||
echo "Data directory: $DATA_DIR"
|
||||
|
||||
# Ensure the data directory exists
|
||||
if [ ! -d "$DATA_DIR" ]; then
|
||||
echo "Creating data directory: $DATA_DIR"
|
||||
mkdir -p "$DATA_DIR"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to create data directory. Trying alternative method..."
|
||||
# Try alternative method if standard mkdir fails
|
||||
cd "$APP_DIR" && mkdir -p data
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "ERROR: Both methods to create data directory failed. Please check permissions."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Set permissions
|
||||
chmod -R 755 "$DATA_DIR"
|
||||
|
||||
# Check for RSS files
|
||||
if [ ! -f "$DATA_DIR/rss-feeds.json" ]; then
|
||||
echo "Creating initial empty rss-feeds.json file"
|
||||
echo "[]" > "$DATA_DIR/rss-feeds.json"
|
||||
fi
|
||||
|
||||
if [ ! -f "$DATA_DIR/rss-items.json" ]; then
|
||||
echo "Creating initial empty rss-items.json file"
|
||||
echo "[]" > "$DATA_DIR/rss-items.json"
|
||||
fi
|
||||
|
||||
# Start the application
|
||||
cd "$APP_DIR" || { echo "Failed to change to application directory"; exit 1; }
|
||||
node server.js
|
||||
EOF
|
||||
|
||||
chmod +x "$TEST_START_SCRIPT"
|
||||
log "INFO" "Created test-and-start script at $TEST_START_SCRIPT"
|
||||
|
||||
# Check if service file already exists
|
||||
SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME.service"
|
||||
if [ -f "$SERVICE_FILE" ] && [ "$IS_UPDATE" = true ]; then
|
||||
log "INFO" "Service file already exists. Preserving existing service configuration."
|
||||
|
||||
# Extract existing JWT_SECRET if present to maintain session consistency
|
||||
EXISTING_JWT_SECRET=$(grep "Environment=JWT_SECRET=" "$SERVICE_FILE" | cut -d'=' -f3)
|
||||
|
||||
# Extract existing PORT if it differs from the configured one
|
||||
EXISTING_PORT=$(grep "Environment=PORT=" "$SERVICE_FILE" | cut -d'=' -f3)
|
||||
if [ -n "$EXISTING_PORT" ] && [ "$EXISTING_PORT" != "$PORT" ]; then
|
||||
log "INFO" "Using existing port configuration: $EXISTING_PORT"
|
||||
PORT=$EXISTING_PORT
|
||||
fi
|
||||
|
||||
# Create backup of existing service file
|
||||
backup_file "$SERVICE_FILE"
|
||||
|
||||
# Update the service file while preserving key settings
|
||||
cat > "$SERVICE_FILE" << EOF
|
||||
[Unit]
|
||||
Description=Transmission RSS Manager
|
||||
After=network.target transmission-daemon.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER
|
||||
WorkingDirectory=$INSTALL_DIR
|
||||
ExecStart=$TEST_START_SCRIPT
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
Environment=PORT=$PORT
|
||||
Environment=NODE_ENV=production
|
||||
Environment=DEBUG_ENABLED=false
|
||||
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
||||
Environment=CONFIG_DIR=$CONFIG_DIR
|
||||
EOF
|
||||
|
||||
# Preserve the existing JWT_SECRET if available
|
||||
if [ -n "$EXISTING_JWT_SECRET" ]; then
|
||||
echo "Environment=JWT_SECRET=$EXISTING_JWT_SECRET" >> "$SERVICE_FILE"
|
||||
else
|
||||
echo "# Generate a random JWT secret for security" >> "$SERVICE_FILE"
|
||||
echo "Environment=JWT_SECRET=$(openssl rand -hex 32)" >> "$SERVICE_FILE"
|
||||
fi
|
||||
|
||||
# Close the service file definition
|
||||
cat >> "$SERVICE_FILE" << EOF
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
|
||||
else
|
||||
# For fresh installations, create a new service file
|
||||
log "INFO" "Creating new service file"
|
||||
|
||||
# Create backup of existing service file if it exists
|
||||
if [ -f "$SERVICE_FILE" ]; then
|
||||
backup_file "$SERVICE_FILE"
|
||||
fi
|
||||
|
||||
# Create systemd service file
|
||||
cat > "$SERVICE_FILE" << EOF
|
||||
[Unit]
|
||||
Description=Transmission RSS Manager
|
||||
After=network.target transmission-daemon.service
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=$USER
|
||||
WorkingDirectory=$INSTALL_DIR
|
||||
ExecStart=$TEST_START_SCRIPT
|
||||
Restart=always
|
||||
RestartSec=10
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
Environment=PORT=$PORT
|
||||
Environment=NODE_ENV=production
|
||||
Environment=DEBUG_ENABLED=false
|
||||
Environment=LOG_FILE=$INSTALL_DIR/logs/transmission-rss-manager.log
|
||||
Environment=CONFIG_DIR=$CONFIG_DIR
|
||||
# Generate a random JWT secret for security
|
||||
Environment=JWT_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Create logs directory
|
||||
mkdir -p "$INSTALL_DIR/logs"
|
||||
chown -R $USER:$USER "$INSTALL_DIR/logs"
|
||||
|
||||
# Check if file was created successfully
|
||||
if [ ! -f "$SERVICE_FILE" ]; then
|
||||
log "ERROR" "Failed to create systemd service file"
|
||||
return 1
|
||||
fi
|
||||
|
||||
log "INFO" "Setting up Nginx reverse proxy..."
|
||||
|
||||
# Check if nginx is installed
|
||||
if ! command -v nginx &> /dev/null; then
|
||||
log "ERROR" "Nginx is not installed"
|
||||
log "INFO" "Skipping Nginx configuration. Please configure your web server manually."
|
||||
|
||||
# Reload systemd and enable service
|
||||
systemctl daemon-reload
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
|
||||
log "INFO" "Systemd service has been created and enabled."
|
||||
log "INFO" "The service will start automatically after installation."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Detect nginx configuration directory
|
||||
NGINX_AVAILABLE_DIR=""
|
||||
NGINX_ENABLED_DIR=""
|
||||
|
||||
if [ -d "/etc/nginx/sites-available" ] && [ -d "/etc/nginx/sites-enabled" ]; then
|
||||
# Debian/Ubuntu style
|
||||
NGINX_AVAILABLE_DIR="/etc/nginx/sites-available"
|
||||
NGINX_ENABLED_DIR="/etc/nginx/sites-enabled"
|
||||
elif [ -d "/etc/nginx/conf.d" ]; then
|
||||
# CentOS/RHEL style
|
||||
NGINX_AVAILABLE_DIR="/etc/nginx/conf.d"
|
||||
NGINX_ENABLED_DIR="/etc/nginx/conf.d"
|
||||
else
|
||||
log "WARN" "Unable to determine Nginx configuration directory"
|
||||
log "INFO" "Please configure Nginx manually"
|
||||
|
||||
# Reload systemd and enable service
|
||||
systemctl daemon-reload
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
|
||||
log "INFO" "Systemd service has been created and enabled."
|
||||
log "INFO" "The service will start automatically after installation."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Check if default nginx file exists, back it up if it does
|
||||
if [ -f "$NGINX_ENABLED_DIR/default" ]; then
|
||||
backup_file "$NGINX_ENABLED_DIR/default"
|
||||
if [ -f "$NGINX_ENABLED_DIR/default.bak" ]; then
|
||||
log "INFO" "Backed up default nginx configuration."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Create nginx configuration file
|
||||
NGINX_CONFIG_FILE="$NGINX_AVAILABLE_DIR/$SERVICE_NAME.conf"
|
||||
cat > "$NGINX_CONFIG_FILE" << EOF
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:$PORT;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade \$http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host \$host;
|
||||
proxy_cache_bypass \$http_upgrade;
|
||||
proxy_set_header X-Real-IP \$remote_addr;
|
||||
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto \$scheme;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
log "INFO" "Nginx configured to proxy connections from port 80 to port $PORT"
|
||||
log "INFO" "You can access Transmission RSS Manager at http://your-server-ip/ (port 80) via Nginx"
|
||||
|
||||
# Check if Debian/Ubuntu style (need symlink between available and enabled)
|
||||
if [ "$NGINX_AVAILABLE_DIR" != "$NGINX_ENABLED_DIR" ]; then
|
||||
# Create symbolic link to enable the site (if it doesn't already exist)
|
||||
if [ ! -h "$NGINX_ENABLED_DIR/$SERVICE_NAME.conf" ]; then
|
||||
ln -sf "$NGINX_CONFIG_FILE" "$NGINX_ENABLED_DIR/"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Test nginx configuration
|
||||
if nginx -t; then
|
||||
# Reload nginx
|
||||
systemctl reload nginx
|
||||
log "INFO" "Nginx configuration has been set up successfully."
|
||||
else
|
||||
log "ERROR" "Nginx configuration test failed. Please check the configuration manually."
|
||||
log "WARN" "You may need to correct the configuration before the web interface will be accessible."
|
||||
fi
|
||||
|
||||
# Check for port conflicts
|
||||
if ss -lnt | grep ":$PORT " &> /dev/null; then
|
||||
log "WARN" "Port $PORT is already in use. This may cause conflicts with the service."
|
||||
log "WARN" "The service will fail to start. Please stop any service using port $PORT and try again."
|
||||
else
|
||||
log "INFO" "You can access the web interface at: http://localhost:$PORT or http://your-server-ip:$PORT"
|
||||
log "INFO" "You may need to configure your firewall to allow access to port $PORT"
|
||||
fi
|
||||
|
||||
# Reload systemd
|
||||
systemctl daemon-reload
|
||||
|
||||
# Enable the service to start on boot
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
|
||||
log "INFO" "Systemd service has been created and enabled."
|
||||
log "INFO" "The service will start automatically after installation."
|
||||
}
|
||||
Reference in New Issue
Block a user