Linux设置定时作业执行node.js脚本

需求

定时作业使用puppeteer工具后台打开sapui5 web应用,截图发送到企业微信

1.timer和service文件路径/etc/systemd/system/

service代码

复制代码
[Unit]
Description=1000DayPushWx Service
After=network.target

[Service]
Type=oneshot
User=root
Group=root
WorkingDirectory=/opt/zauto
ExecStart=/usr/bin/node /opt/zauto/1000DayPushWx.js
StandardOutput=journal
StandardError=journal
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

js脚本路径

timer代码

复制代码
[Unit]
Description=Run 1000DayPushWx daily
Requires=1000DayPushWx.service

[Timer]
# 每天上午 9:10 执行
OnCalendar=*-*-* 09:10:00
Persistent=true

[Install]
WantedBy=timers.target 

2.node.js脚本代码

javascript 复制代码
const puppeteer = require('puppeteer');
const fs = require('fs');
const path = require('path');
const os = require('os');

// 日志写入函数
function writeLog(message) {
    const logPath = path.join(__dirname, '1000_day_push.log');
    const time = new Date().toISOString();
    fs.appendFileSync(logPath, `[${time}] ${message}\n`);
    console.log(`[${time}] ${message}`);
}

// 根据操作系统确定Chrome路径
function getChromePath() {
    const platform = os.platform();
    
    if (platform === 'win32') {
        return 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe';
    } else if (platform === 'linux') {
        // Linux 系统下的 Chrome 路径
        const possiblePaths = [
            '/usr/bin/google-chrome',
            '/usr/bin/google-chrome-stable',
            '/usr/bin/chromium',
            '/usr/bin/chromium-browser'
        ];
        
        for (const chromePath of possiblePaths) {
            if (fs.existsSync(chromePath)) {
                return chromePath;
            }
        }
        
        // 如果找不到,让 Puppeteer 使用内置的 Chromium
        return null;
    }
    
    return null;
}

(async () => {
    const chromePath = getChromePath();
    const launchOptions = {
        headless: true,
        args: [
            '--window-size=800,1700',
            '--no-sandbox',
            '--disable-setuid-sandbox',
            '--disable-dev-shm-usage',
            '--disable-gpu',
            '--no-first-run',
            '--no-zygote',
            '--single-process'
        ]
    };
    
    // 如果找到了 Chrome 路径,则使用它
    if (chromePath) {
        launchOptions.executablePath = chromePath;
        writeLog(`使用 Chrome 路径: ${chromePath}`);
    } else {
        writeLog('使用 Puppeteer 内置的 Chromium');
    }
    
    const browser = await puppeteer.launch(launchOptions);
    
    const page = await browser.newPage();
    await page.setViewport({ width: 800, height: 1700 });
    
    // 设置更长的超时时间
    await page.setDefaultTimeout(60000);
    
    // 设置 Basic Auth 账号密码
    await page.authenticate({
        username: 账号,
        password: 密码
    });
    writeLog('已设置Basic Auth');
    
    // 访问页面,等待网络空闲
    await page.goto('http://ip/zfiori_fi06/index.html', {
        waitUntil: 'networkidle2',
        timeout: 60000
    });
    writeLog('页面打开成功');
    
    // 等待 UI5 应用完全初始化
    writeLog('等待UI5应用初始化...');
    await page.waitForFunction(() => {
        return window.sap && 
               window.sap.ui && 
               window.sap.ui.getCore() && 
               window.sap.ui.getCore().getComponent;
    }, { timeout: 30000 });
    writeLog('UI5应用初始化完成');
    
    // 等待页面元素出现,增加重试机制
    writeLog('查找page元素...');
    let pageElement = null;
    let retryCount = 0;
    const maxRetries = 3;
    
    while (!pageElement && retryCount < maxRetries) {
        try {
            pageElement = await page.waitForSelector('[id$="page"]', {
                timeout: 20000,
                visible: true
            });
            writeLog('page元素加载完成');
            break;
        } catch (error) {
            retryCount++;
            writeLog(`第 ${retryCount} 次尝试失败,等待 3 秒后重试...`);
            await page.waitForTimeout(3000);
        }
    }
    
    if (!pageElement) {
        writeLog('ERROR: 无法找到page元素,保存调试截图');
        await page.screenshot({ path: 'debug-page-not-found.png' });
        throw new Error('无法找到page元素');
    }
    
    // 等待页面完全渲染
    await new Promise(resolve => setTimeout(resolve, 5000));
    writeLog('页面渲染完成');
    
    // 等待 VizFrame 元素加载
    writeLog('等待day viz空间加载开始');
    
    const vizSelectors = [
        '[id$="idVizFrame5"]',
        '[id$="idVizFrame6"]',
        '[id$="idVizFrame7"]'
    ];
    
    for (const selector of vizSelectors) {
        try {
            await page.waitForSelector(selector, { 
                timeout: 30000,
                visible: true 
            });
            writeLog(`VizFrame元素 ${selector} 加载完成`);
        } catch (error) {
            writeLog(`ERROR: VizFrame元素 ${selector} 加载失败`);
            // 保存调试截图
            await page.screenshot({ path: `debug-vizframe-${selector}.png` });
            throw error;
        }
    }
    
    writeLog('等待day viz空间加载完成');
    
    // 等待额外时间确保图表完全渲染
    await new Promise(resolve => setTimeout(resolve, 3000));
    writeLog('图表渲染完成');
    
    // 查找并点击截图按钮
    writeLog('查找截图按钮...');
    try {
        await page.waitForSelector('[id$="idjtButton"]', { 
            timeout: 15000,
            visible: true 
        });
        await page.click('[id$="idjtButton"]');
        writeLog('已点击截图按钮');
    } catch (error) {
        writeLog('ERROR: 无法找到或点击截图按钮');
        await page.screenshot({ path: 'debug-button-not-found.png' });
        throw error;
    }
    
    writeLog('已发送日数据');
    
    // 等待操作完成
    await new Promise(resolve => setTimeout(resolve, 5000));
    writeLog('操作完成');
    
    await browser.close();
    writeLog('浏览器已关闭');
    
})().catch(error => {
    writeLog(`脚本执行失败: ${error.message}`);
    process.exit(1);
});

3.启动定时作业的linux命令

启用定时器(开机自启)

systemctl enable 1000DayPushWx.timer

启动定时器

systemctl start 1000DayPushWx.timer

检查状态

systemctl status 1000DayPushWx.timer

看到下图结果,说明启动成功

相关推荐
跃渊Yuey30 分钟前
【Linux】线程同步与互斥
linux·笔记
舰长11533 分钟前
linux 实现文件共享的实现方式比较
linux·服务器·网络
zmjjdank1ng1 小时前
Linux 输出重定向
linux·运维
路由侠内网穿透.1 小时前
本地部署智能家居集成解决方案 ESPHome 并实现外部访问( Linux 版本)
linux·运维·服务器·网络协议·智能家居
VekiSon1 小时前
Linux内核驱动——基础概念与开发环境搭建
linux·运维·服务器·c语言·arm开发
zl_dfq2 小时前
Linux 之 【进程信号】(signal、kill、raise、abort、alarm、Core Dump核心转储机制)
linux
Ankie Wan2 小时前
cgroup(Control Group)是 Linux 内核提供的一种机制,用来“控制、限制、隔离、统计”进程对系统资源的使用。
linux·容器·cgroup·lxc
skywalk81632 小时前
尝试在openi启智社区的dcu环境安装ollama最新版0.15.2(失败)
linux·运维·服务器·ollama
zhengfei6113 小时前
AutoPentestX – Linux 自动化渗透测试和漏洞报告工具
linux·运维·自动化
我材不敲代码3 小时前
在Linux系统上安装MySQL
linux·运维·服务器