node.jscronubuntu-22.04morgan

Cronjob and logging NodeJS project on Ubuntu 22.04


I have a Typescript project using morgan and morgan-daily-rotate for logging. It does HTTP requests on 1 server to fetch some stock information and updates that stock information on another server. When it runs, it generates a folder in a YYYY-MM-DD pattern. I am developing on a Windows machine and deploying to a Linode Ubuntu 22.04 instance.

My project directory:

build/
  ...
  index.js
logs/
  2022-10-04-20/ <- these folders will be generated depending on run date and time
    combined.log
    error.log
    warn.log
src/
  ...
  index.ts
run.sh

The project is placed in ~/customerName/projectName/. During deployment, the Typescript project is built, and only the build folder is copied to the Linode instance along with package.json for installing dependencies.

I have a firewall set up that allows http and https connections. ufw status gives:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80,443/tcp                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80,443/tcp (v6)            ALLOW       Anywhere (v6)

If I run the project on my Windows machine during development it runs perfectly fine and logs appear nicely in different date directories in the logs directory.

If I run the project on the Ubuntu instance from ~/customerName/projectName/, it also works perfectly fine just like development.

However when I start the command from a cronjob:

*/5 * * * * cd /home/user/customerName/projectName/ && node index.js > /home/user/customerName/projectName/logs/cron.log 2&>1

The logs end up in ~/logs instead of ~/customerName/projectName/logs even though I tell cron to start from the project directory. Probably because it is executing the cronjob from the user's home directory. Also, the logs are filled with axios errors containing Error: connect ECONNREFUSED ::1:80

An example of a morgan transport:

const infoTransport: DailyRotateFile = new DailyRotateFile({
  level: "info",
  filename: "./logs/%DATE%/combined.log",
  datePattern: "YYYY-MM-DD-HH",
  maxSize: "20m",
  maxFiles: "14d",
});

Questions:

  1. How can I let cron execute the script from the ~/customerName/projectName/ directory?
  2. Why am I getting Error: connect ECONNREFUSED ::1:80 when running the script as the user itself works fine?
  3. A bit offtopic: How should I set environment variables for use during the script?

Thanks in advance.


Solution

  • I found a way to handle this properly. I actually just created exactly the same .env file I use during development in the project directory and set it equal to the BASH_ENV variable.

    my crontab entry:

    0 4 * * * BASH_ENV=/home/user/customerName/projectName/.env /home/user/customerName/projectName/run.sh > /home/user/customerName/projectName/logs/cron.log 2&>1
    

    my run.sh

    #!/bin/sh
    date
    echo Starting customerName stock update on $PROJECTNAME_ENVIRONMENT
    cd /home/user/customerName/projectName
    /home/user/.nvm/versions/node/v16.17.1/bin/node index.js