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

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

相关推荐
scilwb2 小时前
Isaac Sim机械臂教程 - 阶段2:场景构建与物体创建
linux
Code Warrior2 小时前
【Linux】Ext系列文件(1)
linux
源去_云走2 小时前
npm 包构建与发布
前端·npm·node.js
码农欧文2 小时前
关于npm和pnpm
前端·npm·node.js
绛洞花主敏明2 小时前
全缓冲和行缓冲
linux·运维·服务器
艾莉丝努力练剑3 小时前
【Linux指令 (一)】Linux 命令行入门:从零开始理解Linux系统理论核心概念与基础指令
linux·c++·经验分享·ubuntu·centos
DeeplyMind3 小时前
rocr专栏介绍
linux·ai·amdgpu·rocm·rocr·libhsakmt·thunk
namekong84 小时前
在 Ubuntu 上可以用几个常用命令查看系统运行情况(内存、CPU、硬盘占用等
linux·运维·服务器
wheeldown4 小时前
【Linux】Linux下的静态链接的底层逻辑
linux·运维·服务器