Node forever 说程序是 运行,但证据表明不是

Node forever says program is running, but evidence suggests not

我正在尝试 运行 使用 twit library and forever 的简单 twitterbot。该机器人本质上是在监视另一个推特帐户,并复制其推文并进行一些修改。

我一直在记录从流式传输 API 收到的推文,并记录所有错误。

然而,bot 经常会停止工作,同时记录没有错误,而 forever list 仍然显示程序为 运行ning。

info:    Forever processes running
data:        uid  command         script forever pid   id logfile                        uptime        
data:    [0] QOmt /usr/bin/nodejs bot.js 13642   13649    /home/ubuntu/.forever/QOmt.log 0:5:25:34.733

起初,我认为这可能是 Twitter 流媒体的问题 API - 即信息已停止发送 "down the pipe",因为日志文件已停止记录来自推特流 API.

为了验证机器人确实还在 运行ning,我创建了一个 heartbeat 每分钟记录一次。

// Heartbeat to make sure the process is still running
setInterval(function () {
  console.logWithDate('Program heartbeat');
}, 60*1000);

当机器人停止运行时,心跳也会停止记录。然而 forever 仍然说机器人是 运行ning。

非常感谢任何帮助。我 post 下面是我的机器人的完整代码,以防有用。

#!/usr/bin/env node
"use strict"

const fs = require('fs');
const util = require('util');
const Twit = require('twit');

// Logging
const error_log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'a'});
const log_stdout = process.stdout;

console.error = function(d) {
  error_log_file.write(util.format("\n%s> %s", new Date(), d) + '\n');
  log_stdout.write(util.format("\n%s> %s", new Date(), d) + '\n');
};

console.logWithDate = function(d) {
    log_stdout.write(util.format("\n%s> %s", new Date(), d) + '\n');
}

// Heartbeat to make sure the process is still running
setInterval(function () {
  console.logWithDate('Program heartbeat');
}, 60*1000);


// Read in twitter secrets file
const twitter_secrets = JSON.parse(fs.readFileSync("twitter_secrets.json"));


// Connect to twitter
const client = new Twit({
    consumer_key: twitter_secrets.TWITTER_CONSUMER_KEY,
    consumer_secret: twitter_secrets.TWITTER_CONSUMER_SECRET,
    access_token: twitter_secrets.TWITTER_ACCESS_TOKEN_KEY,
    access_token_secret: twitter_secrets.TWITTER_ACCESS_TOKEN_SECRET,
    timeouts_ms: 60*1000
});

// Main
const stream = client.stream('statuses/filter', {follow: 87818409});
stream.on('tweet', function(event) {
    if (event.user.id === 87818409) {
        console.logWithDate("Guardian tweet: " + event.text)
        client.post(
            'statuses/update',
            {status: misspellRandomWords(event.text)},
            function(error, tweet, response) {
                if (error) {
                    console.error(error);
                } else {
                    console.logWithDate("Bot tweet: " + tweet.text);  // Tweet body.
                    //console.log(response);  // Raw response object.
                }
            }
        );
    } else {
        console.logWithDate("Guardian-related tweet: " + event.text)
    }
});

// Log various types of messages for debugging
stream.on('limit', function(error) {
    console.error(error);
});

stream.on('disconnect', function(error) {
    console.error(error);
});

stream.on('error', function(error) {
    console.error(error);
});

stream.on('connect', function (conn) {
  console.logWithDate('connecting')
})

stream.on('reconnect', function (reconn, res, interval) {
  console.logWithDate('reconnecting. statusCode:', res.statusCode)
})


/* Helper functions */

function swapRandomLetters(word) {
    const limit = word.length;
    const iFirstLetter = Math.floor(Math.random() * limit);
    var iSecondLetter = Math.floor(Math.random() * limit);

    while (iFirstLetter === iSecondLetter) {
        iSecondLetter = Math.floor(Math.random() * limit);
    }

    let letters = word.split("");
    letters[iFirstLetter] = word[iSecondLetter];
    letters[iSecondLetter] = word[iFirstLetter];
    return letters.join("");
}

function isLink(word) {
    // Very crude URL check
    return word.substring(0,4) === "http";
}

function misspellRandomWords(sentence) {
    let words = sentence.split(" ");
    const limit = words.length;

    // Choose a first word, filtering out urls
    var iFirstWord = Math.floor(Math.random() * limit);
    while (isLink(words[iFirstWord]) || words[iFirstWord][0] === "@" ) {
        iFirstWord = Math.floor(Math.random() * limit);
    }

    // Choose second misspelled word, and make sure it isn't the first or an URL
    var iSecondWord = Math.floor(Math.random() * limit);
    while (isLink(words[iSecondWord]) ||
            iSecondWord === iFirstWord ||
            words[iSecondWord][0] === "@") {
        iSecondWord = Math.floor(Math.random() * limit);
    }

    words[iFirstWord] = swapRandomLetters(words[iFirstWord]);
    words[iSecondWord] = swapRandomLetters(words[iSecondWord]);

    return words.join(" ");
}

如果一条推文的所有单词都以 @ 开头,就会出现死循环,从而阻塞主线程。