UPDATE: index.js file content added.
I have this electron app that is executing some bash scrips(*.sh) files to perform some task.
Everything is working absolutely fine in the development environment but when building the production build for deb
installer for Ubuntu platform, everything is working, like opening on the app, other NodeJS stuff, but bash scripts are not executing.
Problem Statement: How to execute shell scripts in the production build of an electron app for Linux(Ubuntu OS). Getting this error
app/terminal_scripts/timer.sh Not Found
Below are the detailed explanation for the app.
Where inside the app directory, I have all CSS, images, js, HTML, and terminal scripts.
package.json:
{
"name": "timer",
"productName": "Timely",
"version": "1.0.25",
"description": "This desktop app shows you system clock",
"main": "app/js/main/index.js",
"scripts": {
"start": "electron .",
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "nodemon --exec 'electron .'",
"dist": "electron-builder"
},
"homepage": ".",
"keywords": [
"Electron",
"Desktop App"
],
"author": "NotABot Ltd <[email protected]>",
"contributors": [
{
"name": "Not A Bot",
"email": "[email protected]"
}
],
"license": "ISC",
"dependencies": {
"desandro-matches-selector": "^2.0.2",
"electron-context-menu": "^1.0.0",
"electron-is": "^3.0.0",
"fix-path": "^3.0.0",
"isotope-layout": "^3.0.6",
"jquery": "^3.5.0",
"jquery-bridget": "^2.0.1"
},
"build": {
"appId": "com.test.timely",
"productName": "Timely",
"linux": {
"target": "deb",
"category": "System"
}
},
"devDependencies": {
"electron": "^8.1.1",
"electron-builder": "^22.6.0"
}
}
HTML:
<html>
<head>
<title>Timely</title>
</head>
<body>
<button onclick="displayTime()">Display Time</button>
<textarea rows="20" cols="90" id="command-output" disabled="true"></textarea>
<script>
const {app} = require('electron');
function displayTime(){
console.log("button clicked");
let cmd = `bash app/terminal_scripts/timer.sh`;
let completeMessage = 'This is the message';
backgroundProcess(cmd, completeMessage);
}
function getCommandOutput() { return document.getElementById("command-output"); };
function getStatus() { return document.getElementById("status"); };
function appendOutput(msg) { getCommandOutput().value += (msg+'\n'); };
function setStatus(msg) { getStatus().innerHTML = msg; };
function backgroundProcess(cmd, completeMessage){
const process = require('child_process');
var child = process.execFile(cmd, [] , {shell: true} );
appendOutput("Processing......");
child.on('error', function(err) {
appendOutput('stderr: '+err );
});
child.stdout.on('data', function (data) {
appendOutput(data);
});
child.stderr.on('data', function (data) {
appendOutput(data );
});
return new Promise((resolve, reject) => {
child.on('close', function (code) {
console.log(`code is: ${code}`);
if (code == 0){
setStatus(completeMessage);
resolve(1);
}
else{
setStatus('Exited with error code ' + code);
resolve(-1);
}
});
});
}
</script>
</body>
</html>
Bash Script:
#!/bin/bash
timer="$(date)"
echo "$timer"
Permission is set 777 for this shell file
Platform Information:
index.js
const {app, BrowserWindow, Menu, Tray, ipcMain, MenuItem} = require('electron');
const path = require('path');
const contextMenu = require('electron-context-menu');
let splashWindow;
function createMainWindow(){
mainWindow = new BrowserWindow({
minHeight: 700,
minWidth: 800,
webPreferences: {
nodeIntegration: true,
webviewTag: true
},
show: false
});
//For dev only
// mainWindow.webContents.openDevTools();
mainWindow.loadFile('app/renderer/index.html');
mainWindow.maximize();
}
app.on('ready', () =>{
createMainWindow();
});
I have created a new directory alongside the app
directory called the termainal_scripts
.
Inside this, I have my bash file timer.sh.
I figured out how to execute shell scripts, in production by using process.resourcesPath
inside path.join()
.
So, let the fixed path be as:
let fixedURL = path.join(process.resourcesPath, '/terminal_scripts/');
Then the command to execute will be:
let cmd = `${fixedURL}timer.sh`