# Show Node-RED logs from within Node-RED (Linux only)

**URL:** <https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269>\
**Category:** Share Your Projects\
**Tags:** function-node, log\
**Created:** [25 May 2025 21:15 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269 "2025-05-25T21:15:07Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [25 May 2025 21:15 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/1 "2025-05-25T21:15:07Z")

</div>

I know that some folk have difficulty accessing Node-RED logs and sharing them. So it occurred to me that it might be useful to be able to surface the log in Node-RED itself.

Then you could forward it anywhere you like. To a UIBUILDER page for example 😉

So here is a test flow that does the first part.

```json
[{"id":"4ae8ae735f8ce4f8","type":"group","z":"4a3fcf357a20bf56","name":"TEST: Acces to journalctl","style":{"label":true},"nodes":["7ffadef3ea96cc9d","a6b7bf014cec9e5c","fa7b810c980cd879","4bc60421eda247ff"],"x":94,"y":1499,"w":552,"h":122},{"id":"7ffadef3ea96cc9d","type":"inject","z":"4a3fcf357a20bf56","g":"4ae8ae735f8ce4f8","name":"journalctl","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"0","topic":"journalctl","payload":"nrmain","payloadType":"str","x":220,"y":1540,"wires":[["a6b7bf014cec9e5c"]]},{"id":"a6b7bf014cec9e5c","type":"function","z":"4a3fcf357a20bf56","g":"4ae8ae735f8ce4f8","name":"set up/cancel journalctl","func":"// const Journalctl = require('journalctl')\n\n/* \n identifier: Just output logs of the given syslog identifier (cf. man journalctl, option '-t')\n unit: Just output logs originated from the given unit file (cf. man journalctl, option '-u')\n filter: An array of matches to filter by (cf. man journalctl, matches)\n all: Show all fields in full, even if they include unprintable characters or are very long. (cf. man journalctl, option '-a')\n lines: Show the most recent journal events and limit the number of events shown (cf. man journalctl, option '-n')\n since: Start showing entries on or newer than the specified date (cf. man journalctl, option '-S')\n*/\nconst opts = {\n unit: msg.payload,\n lines: 50, // to allow for flows not starting immediately\n}\n\n// We have to track this to be able to cancel it\nlet journalctl = global.get('journalctl')\n\n// If already exists, done run again\nif (journalctl) {\n // 'stop' will end the listener, unload the lib and delete the global\n if (msg.payload === 'stop') {\n node.warn('stopping journalctl')\n journalctl.stop( () => {\n global.set('journalctl', undefined)\n })\n return\n }\n\n node.warn('journalctl is already running.\\nSend a payload of \"stop\" to end.')\n return\n}\n\n// If it doesn't exist, create and save the reference\njournalctl = new Journalctl(opts)\nglobal.set('journalctl', journalctl)\n\n\n// Set up a persistent listener for new journal entries\n// NOTE: THIS WILL CARRY ON WORKING\n// Even after the function node completes\n// You only ever need to run it once\njournalctl.on('event', (event) => {\n node.send({\n topic: 'journalctl-event',\n payload: event,\n })\n})\nnode.warn('journalctl listener started')","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[{"var":"Journalctl","module":"journalctl"}],"x":420,"y":1540,"wires":[["fa7b810c980cd879"]]},{"id":"fa7b810c980cd879","type":"debug","z":"4a3fcf357a20bf56","g":"4ae8ae735f8ce4f8","name":"journalctl","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload.MESSAGE","targetType":"msg","statusVal":"","statusType":"counter","x":585,"y":1540,"wires":[],"l":false},{"id":"4bc60421eda247ff","type":"inject","z":"4a3fcf357a20bf56","g":"4ae8ae735f8ce4f8","name":"journalctl-stop","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"0","topic":"journalctl-stop","payload":"stop","payloadType":"str","x":210,"y":1580,"wires":[["a6b7bf014cec9e5c"]]}]

```

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/4/742efe5557d7ab79ce1360504781683021f0afd2.png)  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/c/8c0f00e1894708594fb899dc0775db5fdac8f019.png)

You will need to change the systemd service name in the inject called `journalctl` to whatever you are using - mine is set to something custom.

Note that you will probably also need to use `visudo -e` to let your node-red user to run `journalctl` without a password. Please let me know cause my server is already set up that way.

There is a slight issue in that flows don't start until a couple of seconds after Node-RED has started, so this flow doesn't show the startup log even though I've told it to show 50 lines. Stopping and restarting does the trick. I'll try to find a way around that.

So not perfect but may be of use.

_Let me know if you want to see a UIBUILDER page that shows the log._

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [26 May 2025 17:42 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/2 "2025-05-26T17:42:04Z")

</div>

Hi Julian,

Thanks for this.  
I did make 2 changes.

- Ensure things are disposed of, if the Node is deleted. I feel this is often overlooked (by myself included)

```auto
/* On Stop */
const journalctl = global.get('journalctl')
if (journalctl) {
    node.warn('stopping journalctl')
    journalctl.stop(() => {
        global.set('journalctl', undefined)
    })
}

```

- When sending "stop", and it already is stopped, it creates another instance - So I only start if payload IS NOT `stop`

```auto
if(msg.payload !== 'stop'){
    journalctl = new Journalctl(opts)
    global.set('journalctl', journalctl)

    // Set up a persistent listener for new journal entries
    // NOTE: THIS WILL CARRY ON WORKING
    // Even after the function node completes
    // You only ever need to run it once
    journalctl.on('event', (event) => {
        node.send({
            topic: 'journalctl-event',
            payload: event,
        })
    })
    node.warn('journalctl listener started')
}

```

Changes

```auto
[{"id":"4ae8ae735f8ce4f8","type":"group","z":"7eb0ef81c62ddec8","name":"TEST: Acces to journalctl","style":{"label":true},"nodes":["7ffadef3ea96cc9d","a6b7bf014cec9e5c","fa7b810c980cd879","4bc60421eda247ff"],"x":254,"y":244,"w":552,"h":122},{"id":"7ffadef3ea96cc9d","type":"inject","z":"7eb0ef81c62ddec8","g":"4ae8ae735f8ce4f8","name":"journalctl","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":"0","topic":"journalctl","payload":"nrmain","payloadType":"str","x":380,"y":285,"wires":[["a6b7bf014cec9e5c"]]},{"id":"a6b7bf014cec9e5c","type":"function","z":"7eb0ef81c62ddec8","g":"4ae8ae735f8ce4f8","name":"set up/cancel journalctl","func":"// const Journalctl = require('journalctl')\n\n/* \n identifier: Just output logs of the given syslog identifier (cf. man journalctl, option '-t')\n unit: Just output logs originated from the given unit file (cf. man journalctl, option '-u')\n filter: An array of matches to filter by (cf. man journalctl, matches)\n all: Show all fields in full, even if they include unprintable characters or are very long. (cf. man journalctl, option '-a')\n lines: Show the most recent journal events and limit the number of events shown (cf. man journalctl, option '-n')\n since: Start showing entries on or newer than the specified date (cf. man journalctl, option '-S')\n*/\nconst opts = {\n unit: msg.payload,\n lines: 50, // to allow for flows not starting immediately\n}\n\n// We have to track this to be able to cancel it\nlet journalctl = global.get('journalctl')\n\n// If already exists, done run again\nif (journalctl) {\n // 'stop' will end the listener, unload the lib and delete the global\n if (msg.payload === 'stop') {\n node.warn('stopping journalctl')\n journalctl.stop( () => {\n global.set('journalctl', undefined)\n })\n return\n }\n\n node.warn('journalctl is already running.\\nSend a payload of \"stop\" to end.')\n return\n}\n\n// If it doesn't exist, create and save the reference, Only if not stopping\nif(msg.payload !== 'stop'){\n journalctl = new Journalctl(opts)\n global.set('journalctl', journalctl)\n\n // Set up a persistent listener for new journal entries\n // NOTE: THIS WILL CARRY ON WORKING\n // Even after the function node completes\n // You only ever need to run it once\n journalctl.on('event', (event) => {\n node.send({\n topic: 'journalctl-event',\n payload: event,\n })\n })\n node.warn('journalctl listener started')\n}\n\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"const journalctl = global.get('journalctl')\nif (journalctl) {\n node.warn('stopping journalctl')\n journalctl.stop(() => {\n global.set('journalctl', undefined)\n })\n}","libs":[{"var":"Journalctl","module":"journalctl"}],"x":580,"y":285,"wires":[["fa7b810c980cd879"]]},{"id":"fa7b810c980cd879","type":"debug","z":"7eb0ef81c62ddec8","g":"4ae8ae735f8ce4f8","name":"journalctl","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload.MESSAGE","targetType":"msg","statusVal":"","statusType":"counter","x":745,"y":285,"wires":[],"l":false},{"id":"4bc60421eda247ff","type":"inject","z":"7eb0ef81c62ddec8","g":"4ae8ae735f8ce4f8","name":"journalctl-stop","props":[{"p":"topic","vt":"str"},{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"0","topic":"journalctl-stop","payload":"stop","payloadType":"str","x":370,"y":325,"wires":[["a6b7bf014cec9e5c"]]}]

```

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [26 May 2025 17:45 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/3 "2025-05-26T17:45:21Z")

</div>

Nice, thanks for that. I will add to my reference flow.

It is weird because the main logic took me far too long to work out - I miss not having GitHub Copilot in the function node editor! Strange how quickly you come to lean on it. 🤷

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [26 May 2025 17:49 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/4 "2025-05-26T17:49:00Z")

</div>

I cant tell you how many times I create an instance of something, and wonder why it is still running.... realising I didn't kill it in the `on stop` tab 😬

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [30 May 2025 17:02 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/5 "2025-05-30T17:02:11Z")

</div>

> [@TotallyInformation](#):
>
> not having GitHub Copilot in the function node editor

Just paste the text into a new file in VS code ?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [30 May 2025 19:59 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/6 "2025-05-30T19:59:06Z")

</div>

> [@Sean-McG](#):
>
> Just paste the text into a new file in VS code ?

Yes, but then you loose the Node-RED context and don't get the smart help with the RED and node objects.

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [31 May 2025 08:35 UTC](https://discourse.nodered.org/t/show-node-red-logs-from-within-node-red-linux-only/97269/7 "2025-05-31T08:35:31Z")

</div>

I guess you could clone node red project and use as a reference 😉
