diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..77665436 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,87 @@ +FROM ubuntu + +# Install SSH and other dependencies +RUN apt update && apt install -y openssh-server +RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config + +# Install necessary tools and libraries +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils && \ + apt-get install -y -q wget \ + build-essential \ + python3 \ + unzip \ + libbsd-dev \ + git \ + sudo \ + vim \ + curl \ + make \ + clang \ + iproute2 \ + net-tools \ + unzip \ + iputils-ping \ + mosquitto \ + mosquitto-clients \ + libmosquitto-dev \ + redis-server \ + redis-tools \ + libhiredis-dev \ + libevent-dev \ + tmux \ + inotify-tools + +# Create an admin user with sudo privileges +RUN useradd -m admin && echo "admin:admin" | chpasswd && adduser admin sudo +RUN echo "admin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers +USER admin + +# Set up Node.js +WORKDIR /home/admin +RUN wget https://deb.nodesource.com/setup_20.x && chmod +x ./setup_20.x && echo admin | sudo -S ./setup_20.x && \ + sudo apt-get install -y -q nodejs + +# Clone JAMScript repository and build dependencies +RUN git clone --branch shahin/migration https://github.com/citelab/JAMScript + +WORKDIR /home/admin/JAMScript/deps +RUN git clone https://github.com/intel/tinycbor && \ + cd tinycbor && \ + make && sudo make install + +WORKDIR /home/admin/JAMScript/deps/mujs2 +RUN make && sudo make install + +# Install JAMScript dependencies and global npm package +WORKDIR /home/admin/JAMScript +RUN npm install +RUN sudo npm install zx -g + +# Additional setup for JAMScript +WORKDIR /home/admin/JAMScript/lib/cside +RUN make archive + +WORKDIR /home/admin +RUN mkdir -p .jamruns && \ + ln -s /home/admin/JAMScript/lib/cside .jamruns/clib && \ + ln -s /home/admin/JAMScript .jamruns/jamhome && \ + ln -s /home/admin/JAMScript/lib/jside .jamruns/node_modules + +# Configure npm global installation path +RUN mkdir .npm-global && mkdir .npm-global/bin +ENV PATH="$PATH:/home/admin/JAMScript/tools:/home/admin/.npm-global/bin" + +# Expose SSH port +EXPOSE 22 + +# Copy the code from the current directory to /home/admin/code in the container +WORKDIR /home/admin/code +COPY . /home/admin/code + +# Run npm install and install.sh as admin +RUN npm install +RUN sudo chmod +x /home/admin/code/install.sh && /home/admin/code/install.sh + +# Start SSH and keep the container running +ENTRYPOINT sudo service ssh start && tail -f /dev/null + diff --git a/README.md b/README.md index 65e8aa00..6379fd32 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,127 @@ -[![Build Status](https://travis-ci.org/citelab/JAMScript.svg?branch=master)](https://travis-ci.org/citelab/JAMScript) +# Redesigning JAMScript Tools for High-Performance and Scalability +This repository is part of an ongoing effort to redesign the JAMScript tools with a focus on high-performance execution and scalable infrastructure. +To achieve this, we've restructured the architecture around a client-server model that separates the responsibilities of coordination and computation. -# A Programming Language and Middleware for Cloud of Moving Things +## 🔧 Getting Started -This project is currently under development. You can see the documentation and install instructions at https://citelab.github.io/JAMScript. +### 1. Clone the Repository + +Start by cloning the repository and switching to the appropriate branch: + +```bash +git clone https://github.com/JeanKa25/JAMScript.git +``` + +Then run the install.sh to install all the dependencies: + + +### 2. Set Environment Variables +Export the following global variables: + +```bash +export JAMHOME=~/JAMScript +export PATH=$JAM_HOME/tools:$PATH +export JAMDATA=~/JAMScript/data +``` + +To make these changes permanent, add them to your .bashrc: + +```bash +echo 'export JAMHOME=~/JAMScript' >> ~/.bashrc +echo 'export PATH=$JAM_HOME/tools:$PATH' >> ~/.bashrc +echo 'export JAMDATA=~/JAMScript/data' >> ~/.bashrc +source ~/.bashrc +``` + + +## ⚙️ Installing Dependencies with Ansible + +You can set up your environment using Ansible with the provided playbook: + +### 1. Install Ansible (if not already installed) + +```bash +sudo apt update +sudo apt install ansible -y +``` + +### 2. Run the setup playbook + +```bash +ansible-playbook setup_jamscript.yml -i localhost, +``` + +> This playbook installs required dependencies, clones the repo, and configures environment variables as needed for JAMScript tools. + +--- + +## 🌐 Running the Server + +To start the JAMScript server, navigate to the tools directory and run the server file: + +```bash +cd ~/JAMScript/tools +node app-docker.js +``` + +### 🔧 Path and IP Configuration + +Before running the server, make sure to update the following files: + +#### `app-docker.js` +- Set the `serverip` parameter to the IP address of the server. + +#### `Wrapper.mjs` +- Update the following: + - `serverip`: match the IP set in `app-docker.js`. + - Path to JAMScript tools directory. + - Path to your SSH `authorized_keys` file (used for key-based SSH access). + +> These updates ensure that the tools can communicate correctly and execute remote tasks securely. + +--- + +### 🚀 Available Ansible Playbooks + +#### Server Run Playbook + +```bash +ansible-playbook serverrun-playbook.yml --extra-vars "server=server2" +``` + +#### JamRun Playbook + +```bash +ansible-playbook jamrun-playbook.yml --extra-vars "server=server2 file=jt1.jxe app='--app=DEMO'" +``` + +#### JamList Playbook + +```bash +ansible-playbook jamlist-playbook.yml --extra-vars "server=server2" +``` + +#### JamTerm Playbook (Without tmux session) + +```bash +ansible-playbook jamterm-playbook.yml --extra-vars "server=server2" +``` + +#### JamTerm Playbook (With tmux session) + +```bash +ansible-playbook jamterm-playbook.yml --extra-vars "server=server2 tmux=u-1001-dev-112-c" +``` + +#### JamKill Playbook + +```bash +ansible-playbook jamkill-playbook.yml --extra-vars "server=server2" +``` + +#### Server Kill Playbook + +```bash +ansible-playbook serverkill-playbook.yml --extra-vars "server=server2" -Programs written in JAMScript have worked in Linux (Arch, Ubuntu, Raspbian) and Mac OS. diff --git a/deps/tinycbor b/deps/tinycbor index e5414c0f..26c63e3d 160000 --- a/deps/tinycbor +++ b/deps/tinycbor @@ -1 +1 @@ -Subproject commit e5414c0ff69561aac32abdbf807b2dae2a35e385 +Subproject commit 26c63e3d5977f77a6483edde4519489254670375 diff --git a/install.sh b/install.sh index 67d0c864..b22b7b9c 100755 --- a/install.sh +++ b/install.sh @@ -149,7 +149,7 @@ cd $SCRIPT_DIR git submodule update --init --recursive lib/ #install tinycbor -cd $SCRIPT_DIR/deps/tinycbor +cd $SCRIPT_DIR/deps git clone https://github.com/intel/tinycbor cd tinycbor make diff --git a/mainCompiler.js b/mainCompiler.js index c4103875..b6c2976c 100755 --- a/mainCompiler.js +++ b/mainCompiler.js @@ -210,7 +210,7 @@ function nativeCompile(code, cargs, userIncludes, userLinkerFlags) { fs.writeFileSync(`${tmpDir}/jamout.c`, code); try { - var command = `clang -g ${tmpDir}/jamout.c -o ${tmpDir}/a.out -I/usr/local/include -I${homeDir}/.jamruns/clib/include -I${homeDir}/.jamruns/clib/src ${options} -pthread -ltinycbor -lmosquitto -lhiredis -levent ${userLinkerFlags.join(" ")} ${homeDir}/.jamruns/clib/libjam.a ${homeDir}/.jamruns/jamhome/deps/mujs2/build/release/libmujs.a -L/usr/local/lib ${includes}`; + var command = `clang -g ${tmpDir}/jamout.c -o ${tmpDir}/a.out -I/usr/local/include -I${homeDir}/.jamruns/clib/include -I${homeDir}/.jamruns/clib/src ${options} -pthread -ltinycbor -lmosquitto -lhiredis -levent ${userLinkerFlags.join(" ")} ${homeDir}/.jamruns/clib/libjam.a ${homeDir}/.jamruns/jamhome/deps/mujs2/build/release/libmujs.a ${homeDir}/.jamruns/jamhome/deps/tinycbor/lib/libtinycbor.a ${includes}`; if (args.verbosity) console.log("[C] Compiling code..."); if (cargs.verbosity == 2) { diff --git a/package.json b/package.json index 28dd1c4c..e8e4669a 100644 --- a/package.json +++ b/package.json @@ -24,22 +24,26 @@ }, "dependencies": { "cbor-x": "1.5.4", - "command-line-args": ">= 3.0.5", + "chokidar": "^3.6.0", + "command-line-args": "^5.2.1", "command-line-usage": "^6.1.0", "express": "^4.18.2", "ioredis": "^5.3.2", "jszip": "^3.10.1", + "lodash": "^4.17.21", "mercator-projection": "^0.0.2", "mqtt": "=4.3.7", + "node-fetch": "^3.3.2", "node-localstorage": ">= 1.3.0", "node-ssh": "^13.1.0", - "ohm-js": "17.1.0", + "ohm-js": "^17.1.0", "pino": "^8.15.0", "ps-node": "^0.1.6", "random-js": "^2.1.0", "redis": "^2.8.0", "toml": "3.0.0", - "ws": "^8.13.0" + "ws": "^8.13.0", + "zx": "^8.3.0" }, "engines": { "node": ">= 12.22", diff --git a/scripts/install/Dockerfile b/scripts/install/Dockerfile index 19413895..3eb17d48 100644 --- a/scripts/install/Dockerfile +++ b/scripts/install/Dockerfile @@ -1,36 +1,81 @@ FROM ubuntu + +# Install OpenSSH server and sudo +RUN apt update && apt install -y openssh-server sudo + +RUN sed -i 's/PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config + RUN apt-get update && apt-get install -y --no-install-recommends apt-utils && \ apt-get install -y -q wget \ build-essential \ - python \ + python3 \ unzip \ libbsd-dev \ git \ sudo \ vim \ curl \ - libssl-dev \ - cmake \ + make \ + clang \ iproute2 \ net-tools \ - iputils-ping \ + unzip \ + iputils-ping + +RUN apt-get install -y -q mosquitto \ + mosquitto-clients \ + libmosquitto-dev + +RUN apt-get install -y -q redis-server \ + redis-tools \ + libhiredis-dev + +RUN apt-get install -y -q libevent-dev \ + tmux \ inotify-tools RUN useradd -m admin && echo "admin:admin" | chpasswd && adduser admin sudo RUN echo "admin ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers USER admin WORKDIR /home/admin -RUN wget https://deb.nodesource.com/setup_13.x && chmod +x ./setup_13.x && echo admin | sudo -S ./setup_13.x && \ +RUN wget https://deb.nodesource.com/setup_20.x && chmod +x ./setup_20.x && echo admin | sudo -S ./setup_20.x && \ sudo apt-get install -y -q nodejs -RUN git clone https://github.com/citelab/JAMScript +RUN git clone --branch master https://github.com/JeanKa25/JAMScript && cd JAMScript/tools && chmod 777 * + -RUN mkdir ~/.npm-global && npm config set prefix '~/.npm-global' +WORKDIR /home/admin/JAMScript/deps +RUN git clone https://github.com/intel/tinycbor +WORKDIR /home/admin/JAMScript/deps/tinycbor +RUN make +RUN sudo make install + +WORKDIR /home/admin/JAMScript/deps/mujs2 +RUN make +RUN sudo make install WORKDIR /home/admin/JAMScript -RUN npm run link -ENV PATH="/home/admin/.npm-global/bin:$PATH" -RUN mkdir /home/admin/temp -WORKDIR /home/admin/temp +RUN npm install +RUN sudo npm install zx -g + +WORKDIR /home/admin/JAMScript/lib/cside +RUN make archive + +WORKDIR /home/admin +RUN mkdir .jamruns +WORKDIR /home/admin/.jamruns +RUN ln -s /home/admin/JAMScript/lib/cside clib +RUN ln -s /home/admin/JAMScript jamhome +RUN ln -s /home/admin/JAMScript/lib/jside node_modules + +WORKDIR /home/admin +RUN mkdir .npm-global +RUN mkdir .npm-global/bin + +ENV PATH="$PATH:/home/admin/JAMScript/tools:/home/admin/.npm-global/bin" + +# Expose the SSH port +EXPOSE 22 -CMD sudo chmod -R a+Xr /etc/avahi && sudo sed -i "s|rlimit-nproc=3|#rlimit-nproc=3 |g" /etc/avahi/avahi-daemon.conf && sudo chmod -R a+Xr /var/run && cd /var/run/ && sudo rm -rf dbus && sudo mkdir dbus && sudo dbus-daemon --system && sudo avahi-daemon +# Start SSH service and keep the container running +ENTRYPOINT ["bash", "-c", "sudo service ssh start && exec bash"] diff --git a/tests/C2J_NoReturnResults/jt1-2.c b/tests/C2J_NoReturnResults/jt1-2.c new file mode 100644 index 00000000..93c016bd --- /dev/null +++ b/tests/C2J_NoReturnResults/jt1-2.c @@ -0,0 +1,25 @@ +jasync localme(int c, char* s) { + jarray int num[5] = {1, 2, 3, 4, 5}; + while(1) { + // jsys.sleep(2000000); + //jsys.dontyield(); + you(s, &num); + // wprintf(L"############-->>> Hello ME %d... %s\n", c, s); + } +} + +jasync localyou(int c, char* s) { + jarray int num[5] = {1, 2, 3, 4, 5}; + while(1) { + jsys.sleep(1000000); + wprintf(L"############-->>> Hello YOU %d, %s\n", c, s); + you(s, &num); + } +} + +int main(int argc, char* argv[]) { + wprintf(L"folks we are printing with wide characters\n"); + localme(FLT_MANT_DIG, "cxxxxyyyy"); + // localyou(hello(), "a-message-for-j: " BAZINGA); + return 0; +} diff --git a/tests/C2J_NoReturnResults/jt1-2.js b/tests/C2J_NoReturnResults/jt1-2.js new file mode 100644 index 00000000..d36e4952 --- /dev/null +++ b/tests/C2J_NoReturnResults/jt1-2.js @@ -0,0 +1,16 @@ +japp nspc { + required_linker_flags:-lm, -lc; + required_clibs: float.h, wchar.h, bazinga.h +} + +let count = 0; + +jasync you(str: char*, num: int[]) { + count++; +// console.log("Message received: ", str, num, " local count ", count); +} + +setInterval(()=> { + console.log("Count ", count); + count = 0; +}, 1000); diff --git a/tests/LocalCalls/test.js b/tests/LocalCalls/test.js new file mode 100644 index 00000000..88e644b1 --- /dev/null +++ b/tests/LocalCalls/test.js @@ -0,0 +1,24 @@ +const { readFileSync } = require('fs'); + +const { Client } = require('ssh2'); + +const conn = new Client(); +conn.on('ready', () => { + console.log('Client :: ready'); + conn.shell((err, stream) => { + if (err) throw err; + stream.on('close', () => { + console.log('Stream :: close'); + conn.end(); + }).on('data', (data) => { + console.log('OUTPUT: ' + data); + }); + stream.end('export PATH=$PATH:$HOME/Programs/JAMScript/tools\n which jamrun.mjs \nexit\n'); + }); +}).connect({ + host: '10.0.1.9', + port: 22, + username: 'maheswar', + password: 'pass4des' +}); + diff --git a/tools/app-docker.js b/tools/app-docker.js new file mode 100644 index 00000000..fa8a220d --- /dev/null +++ b/tools/app-docker.js @@ -0,0 +1,236 @@ +const express = require('express'); +const { exec } = require('child_process'); +const { Client } = require('ssh2'); + +const app = express(); + +const port = 3000; +const host = '0.0.0.0'; +const hostIp = '10.140.16.105'; + +//Start ssh authentication +const fs = require('fs'); + + +// List of authorized SSH public keys +const authorizedKeys = fs + .readFileSync('/home/jamtools/.ssh/authorized_keys', 'utf8') + .split('\n') // Split file into individual keys + .map(key => key.trim()) // Trim spaces and newlines + .filter(key => key.length > 0); // Remove empty lines + + +function checkSSHKey(req, res, next) { + const clientIp = req.connection.remoteAddress; + // Allow local requests without SSH key verification + if (clientIp === '127.0.0.1' || clientIp === '::1' || clientIp === hostIp) { + return next(); // Skip SSH key check for local requests + } + + // Get the SSH key from headers or request body (depending on your client setup) + const sshPublicKey = req.headers['x-ssh-public-key']; // SSH key sent in a header + if (!sshPublicKey) { + console.log('Access Denied: No SSH Key'); + return res.status(401).json({ error: 'No SSH public key provided' }); + } + + // Check if the provided SSH key matches any authorized keys + if (authorizedKeys.includes(sshPublicKey)) { + return next(); // Allow the request if key matches + } else { + console.log('Access Denied: SSH Key not authorized'); + return res.status(403).json({ error: 'SSH key not authorized' }); + } +}; + +app.use(checkSSHKey); +/////////////////// end ssh key authentication + +/// SET WORKING DIRECTORY FOR JAMTOOLS /// +const JAM_HOME = '/home/jamtools/JAMScript'; +const TOOLS_DIR = `${JAM_HOME}/tools`; + +// Update PATH for all commands to ensure JAMTools are available +process.env.PATH = `${TOOLS_DIR}:${process.env.PATH}`; +process.env.JAM_HOME = JAM_HOME; +process.env.JAMHOME = JAM_HOME; +process.env.JAMDATA = `${JAM_HOME}/data`; + +// Middleware to parse JSON requests +app.use(express.json()); + +// Define a simple route +app.get('/api', (req, res) => { + res.json({ message: 'Welcome to the API' }); +}); + +// Utility function to handle command execution and streaming response. **** UPDATE CWD **** +function executeCommand(req, res, command, cwd = '/home/jamtools/JAMScript/tools') { + console.log(`Executing command: ${command}`); + const childProcess = exec(command, { + cwd: TOOLS_DIR, // Set correct working directory + env: process.env, // Use modified environment with updated PATH + }); + + // Set headers to keep the connection open for streaming + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Transfer-Encoding', 'chunked'); + + // Stream stdout data to the client + childProcess.stdout.on('data', (data) => { + res.write(data); + }); + + // Stream stderr data to the client (for debugging or error messages) + childProcess.stderr.on('data', (data) => { + res.write(`Error: ${data}`); + }); + + // When the process completes, close the response + childProcess.on('close', (code) => { + res.end(`\nProcess completed with code ${code}`); + }); + + // Handle any execution errors + childProcess.on('error', (error) => { + res.end(`\nFailed to start process: ${error.message}`); + }); + + // If the client disconnects, terminate the child process + // req.on('close', () => { + // if (childProcess.exitCode === null) { // If process is still running + // console.log('Client disconnected, terminating process'); + // childProcess.kill(); // Terminate the process + // } + // }); +} + +// Define the /jamrun endpoint +app.post('/jamrun', (req, res) => { + const { + file = 'file.jxe', + app_name, + fog, + cloud, + device, + num, + data, + tags, + bg, + old, + log, + verb, + loc, + edge, + valgrind, + local, + remote, + } = req.body; + + if (!app_name) { + return res.status(400).json({ error: 'The "app_name" field is required.' }); + } + + let command = `${TOOLS_DIR}/djam run ${file} --app=${app_name}`; + if (fog) command += ' --fog'; + if (cloud) command += ' --cloud'; + if (device) command += ' --device'; + if (num) command += ` --num=${num}`; + if (data) command += ` --data=${data}`; + if (tags) command += ` --tags="${tags}"`; + if (bg) command += ' --bg'; + if (old) command += ' --old'; + if (log) command += ' --log'; + if (verb) command += ' --verb'; + if (loc) command += ` --loc=${loc}`; + if (edge) command += ` --edge=${edge}`; + if (valgrind) command += ' --valgrind'; + if (local) command += ' --local'; + if (remote) command += ` --remote=${remote}`; + + executeCommand(req, res, command); +}); + +// Define the /jambatch endpoint + app.post('/jambatch', (req, res) => { + const { + file = 'jt1.jxe', device_num,app + } = req.body; + + let command = `${TOOLS_DIR}/djambatch ${file} --device_num=${device_num} --app=${app} --bg `; + + executeCommand(req, res, command); + }); + +// Define the /jamlog endpoint +app.post('/jamlog', (req, res) => { + const { help, program, app, port, remote, tail, c, j } = req.body; + + // Default command without arguments if none are specified + let command = `${TOOLS_DIR}/djam log`; + if (help) command += ` --help`; + if (program) command += ` --program=${program}`; + if (app) command += ` --app=${app}`; + if (port) command += ` --port=${port}`; + if (remote) command += ` --remote=${remote}`; + if (tail) command += ` --tail=${tail}`; + + if (c) command += ` --c`; + if (j) command += ` --j`; + + executeCommand(req, res, command); + +}); + +app.post('/jamlist', (req, res) => { + const { help, all, monitor, type, dataStore, tmuxid, port, app, prog, remote } = req.body; + + // Default command without arguments if none are specified + let command = `${TOOLS_DIR}/djam list`; + if (help) command += ` --help`; + if (all) command += ` --all`; + if (monitor) command += ` --monitor`; + if (type) command += ` --type==${type}`; + if (dataStore) command += ` --dataStore==${dataStore}`; + if (tmuxid) command += ` --tmuxid==${tmuxid}`; + if (port) command += ` --port==${port}`; + if (app) command += ` --app==${app}`; + if (prog) command += ` --prog==${prog}`; + if (remote) command += ` --remote`; + + executeCommand(req, res, command); +}); + +// Define the /jamkill endpoint +app.post('/jamkill', (req, res) => { + const { reset, all, remote, app, prog, port } = req.body; + + let command = `${TOOLS_DIR}/djam kill`; + if (reset) command += ' --reset'; + if (all) command += ' --all'; + if (remote) command += ` --remote=${remote}`; + if (app) command += ` --app==${app}`; + if (prog) command += ` --prog==${prog}`; + if (port) command += ` --port==${port}`; + + executeCommand(req, res, command); +}); + +// Define the /jamterm endpoint +app.post('/jamterm', (req, res) => { + const { tmux_id, terminal_number } = req.body; + console.log (req.body) + + let command = `${TOOLS_DIR}/djam term`; + console.log(`tmux_id entered : ${tmux_id}`) + if (tmux_id) command += ` ${tmux_id}`; + console.log(`terminal_number entered : ${terminal_number}`) + if (terminal_number) command += ` -t ${terminal_number}`; + + executeCommand(req, res, command); +}); + +// Start the server +app.listen(port, host, () => { + console.log(`Server is running on http://${host}:${port}`); +}); diff --git a/tools/app.js b/tools/app.js new file mode 100644 index 00000000..dc9c5896 --- /dev/null +++ b/tools/app.js @@ -0,0 +1,238 @@ +const express = require('express'); +const { exec } = require('child_process'); +const { Client } = require('ssh2'); + +const app = express(); + +const port = 3000; +const host = '0.0.0.0'; +const hostIp = '10.140.16.105'; + +//Start ssh authentication +const fs = require('fs'); + + +// List of authorized SSH public keys +const authorizedKeys = fs + .readFileSync('/home/jamtools/.ssh/authorized_keys', 'utf8') + .split('\n') // Split file into individual keys + .map(key => key.trim()) // Trim spaces and newlines + .filter(key => key.length > 0); // Remove empty lines + + +function checkSSHKey(req, res, next) { + const clientIp = req.connection.remoteAddress; + // Allow local requests without SSH key verification + if (clientIp === '127.0.0.1' || clientIp === '::1' || clientIp === hostIp) { + return next(); // Skip SSH key check for local requests + } + + // Get the SSH key from headers or request body (depending on your client setup) + const sshPublicKey = req.headers['x-ssh-public-key']; // SSH key sent in a header + if (!sshPublicKey) { + console.log('Access Denied: No SSH Key'); + return res.status(401).json({ error: 'No SSH public key provided' }); + } + + // Check if the provided SSH key matches any authorized keys + if (authorizedKeys.includes(sshPublicKey)) { + return next(); // Allow the request if key matches + } else { + console.log('Access Denied: SSH Key not authorized'); + return res.status(403).json({ error: 'SSH key not authorized' }); + } +}; + +app.use(checkSSHKey); +/////////////////// end ssh key authentication + + +// Middleware to parse JSON requests +app.use(express.json()); + +// Define a simple route +app.get('/api', (req, res) => { + res.json({ message: 'Welcome to the API' }); +}); + +// Utility function to handle command execution and streaming response +function executeCommand(req, res, command, cwd = '/home/jamtools/JAMScript/tools/') { + console.log(`Executing command: ${command}`); + const childProcess = exec(command, { cwd }); + + // Set headers to keep the connection open for streaming + res.setHeader('Content-Type', 'text/plain'); + res.setHeader('Transfer-Encoding', 'chunked'); + + // Stream stdout data to the client + childProcess.stdout.on('data', (data) => { + res.write(data); + }); + + // Stream stderr data to the client (for debugging or error messages) + childProcess.stderr.on('data', (data) => { + res.write(`Error: ${data}`); + }); + + // When the process completes, close the response + childProcess.on('close', (code) => { + res.end(`\nProcess completed with code ${code}`); + }); + + // Handle any execution errors + childProcess.on('error', (error) => { + res.end(`\nFailed to start process: ${error.message}`); + }); + + // If the client disconnects, terminate the child process + // req.on('close', () => { + // if (childProcess.exitCode === null) { // If process is still running + // console.log('Client disconnected, terminating process'); + // childProcess.kill(); // Terminate the process + // } + // }); +} + +// Define the /jamrun endpoint +app.post('/jamrun', (req, res) => { + const { + file = 'file.jxe', + app_name, + fog, + cloud, + device, + num, + data, + tags, + bg, + old, + log, + verb, + loc, + edge, + valgrind, + local, + remote, + } = req.body; + + if (!app_name) { + return res.status(400).json({ error: 'The "app_name" field is required.' }); + } + + let command = `zx jamrun.mjs ${file} --app=${app_name}`; + if (fog) command += ' --fog'; + if (cloud) command += ' --cloud'; + if (device) command += ' --device'; + if (num) command += ` --num=${num}`; + if (data) command += ` --data=${data}`; + if (tags) command += ` --tags="${tags}"`; + if (bg) command += ' --bg'; + if (old) command += ' --old'; + if (log) command += ' --log'; + if (verb) command += ' --verb'; + if (loc) command += ` --loc=${loc}`; + if (edge) command += ` --edge=${edge}`; + if (valgrind) command += ' --valgrind'; + if (local) command += ' --local'; + if (remote) command += ` --remote=${remote}`; + + executeCommand(req, res, command); +}); + +// Define the /jambatch endpoint +app.post('/jambatch', (req, res) => { + const { + fog, device, cloud, cFile, fFile, dFile, num, cLoc, fLoc, dLoc, cEdge, fEdge, dEdge + } = req.body; + + let command = `zx jambatch.mjs`; + if (fog) command += ` --fog=${fog}`; + if (device) command += ` --device=${device}`; + if (cloud) command += ` --cloud=${cloud}`; + if (cFile) command += ` --cFile=${cFile}`; + if (fFile) command += ` --fFile=${fFile}`; + if (dFile) command += ` --dFile=${dFile}`; + if (num) command += ` --num=${num}`; + if (cLoc) command += ` --cLoc=${cLoc}`; + if (fLoc) command += ` --fLoc=${fLoc}`; + if (dLoc) command += ` --dLoc=${dLoc}`; + if (cEdge) command += ` --cEdge=${cEdge}`; + if (fEdge) command += ` --fEdge=${fEdge}`; + if (dEdge) command += ` --dEdge=${dEdge}`; + + executeCommand(req, res, command); +}); + +// Define the /jamlog endpoint +app.post('/jamlog', (req, res) => { + const { help, program, app, port, remote, tail, c, j } = req.body; + + // Default command without arguments if none are specified + let command = `zx jamlog.mjs`; + if (help) command += ` --help`; + if (program) command += ` --program=${program}`; + if (app) command += ` --app=${app}`; + if (port) command += ` --port=${port}`; + if (remote) command += ` --remote=${remote}`; + if (tail) command += ` --tail=${tail}`; + + if (c) command += ` --c`; + if (j) command += ` --j`; + + executeCommand(req, res, command); + +}); + +app.post('/jamlist', (req, res) => { + const { help, all, monitor, type, dataStore, tmuxid, port, app, prog, remote } = req.body; + + // Default command without arguments if none are specified + let command = `zx jamlist.mjs`; + if (help) command += ` --help`; + if (all) command += ` --all`; + if (monitor) command += ` --monitor`; + if (type) command += ` --type==${type}`; + if (dataStore) command += ` --dataStore==${dataStore}`; + if (tmuxid) command += ` --tmuxid==${tmuxid}`; + if (port) command += ` --port==${port}`; + if (app) command += ` --app==${app}`; + if (prog) command += ` --prog==${prog}`; + if (remote) command += ` --remote`; + + executeCommand(req, res, command); +}); + +// Define the /jamkill endpoint +app.post('/jamkill', (req, res) => { + const { reset, all, remote, app, prog, port } = req.body; + + let command = 'zx jamkill.mjs'; + if (reset) command += ' --reset'; + if (all) command += ' --all'; + if (remote) command += ` --remote=${remote}`; + if (app) command += ` --app==${app}`; + if (prog) command += ` --prog==${prog}`; + if (port) command += ` --port==${port}`; + + executeCommand(req, res, command); +}); + +// Define the /jamterm endpoint +app.post("/jamterm", (req, res) => { + const { all, app, prog, port, pane } = req.body; + + let command = `zx jamterm.mjs`; + if (all) command += ' --all'; + if (app) command += ` --app==${app}`; + if (prog) command += ` --prog==${prog}`; + if (port) command += ` --port==${port}`; + if (pane) command += ` --pane=${pane}`; + + executeCommand(req, res, command); +}); + +// Start the server +app.listen(port, host, () => { + console.log(`Server is running on http://${host}:${port}`); +}); + diff --git a/tools/batchConfig/config.json b/tools/batchConfig/config.json new file mode 100644 index 00000000..b8afdd40 --- /dev/null +++ b/tools/batchConfig/config.json @@ -0,0 +1,30 @@ +{ + "jobs": [ + { + "name":"XX", + "file":"jt2.jxe", + "type":"device", + "num":"2", + "loc":"300,400", + "edge":"1", + "verb": true + + }, + { + "name":"XXX", + "file":"jt2.jxe", + "type":"fog", + "loc":"100,100", + "edge":"1", + "verb": true + }, + { + "name":"X", + "file":"jt2.jxe", + "type":"cloud", + "loc":"300,400", + "edge":"1" + + } + ] + } \ No newline at end of file diff --git a/tools/chalk.mjs b/tools/chalk.mjs new file mode 100644 index 00000000..a5940303 --- /dev/null +++ b/tools/chalk.mjs @@ -0,0 +1,37 @@ +#!/usr/bin/env zx + +export function header_1(txt){ + return chalk.bgGreen.black.bold.inverse(txt) +} + +export function header_2(txt){ + return chalk.bgBlack.cyan.bold.italic(txt) +} + +export function body_1(txt){ + return chalk.bgBlack.bold.cyan(txt) +} +export function body_sec(txt){ + return chalk.dim.italic(txt) +} +export function body_sec_warning(txt){ + return chalk.dim.yellow.italic(txt) +} + +export function body_2(txt){ + return chalk.dim(txt) +} +export function body_2_line(txt){ + return chalk.dim.underline(txt) +} +export function body_2_bold(txt){ + return chalk.dim.bold(txt) +} + +export function keyWord(txt){ + return chalk.italic.underline(txt) +} + +export function bodyBold(txt){ + return chalk.bold(txt) +} \ No newline at end of file diff --git a/tools/cleanUp.mjs b/tools/cleanUp.mjs new file mode 100644 index 00000000..267bffa5 --- /dev/null +++ b/tools/cleanUp.mjs @@ -0,0 +1,184 @@ +#!/usr/bin/env zx + +import {getJamFolder,getAppFolder, getPaths} from './fileDirectory.mjs' +const { spawnSync } = require('child_process'); +const p2 = spawnSync('which', ['tmux']); +import { + body_sec_warning, +} from "./chalk.mjs"; + +const TMUX = p2.stdout.toString().trim() + +function getTmuxIds(PortNumber,appName , programName){ + const [jamfolder,appfolder,folder] = getPaths(programName,appName); + if(fs.existsSync(`${folder}/${PortNumber}/tmuxid`)){ + const tmuxID = fs.readFileSync(`${folder}/${PortNumber}/tmuxid`).toString().trim(); + const p = spawnSync(TMUX, ['ls', '-F', '#S']); + const runningTMUXS = p.stdout.toString().trim().split("\n"); + const currTmuxids = runningTMUXS.filter((entry) => entry.includes(tmuxID)); + return currTmuxids; + + } + +} +function killtmux(PortNumber,appName , programName){ + const tmuxIds = getTmuxIds(PortNumber,appName , programName) + if(!tmuxIds){ + return + } + for(let id of tmuxIds){ + spawnSync(TMUX, ['kill-session', '-t', id]); + } + + return tmuxIds +} + +function stalePort(removablePort,app,programName){ + const jamfolder = getJamFolder() + if(!removablePort){ + return false; + }; + if(!fs.existsSync(`${jamfolder}/ports/${removablePort}`)){ + return false; + } + + const appNames = fs.readFileSync(`${jamfolder}/ports/${removablePort}`).toString().trim().split("\n"); + const dirName = (programName.split(".")[0])+"_"+app + + + if(appNames.includes(dirName)){ + if(appNames.length === 1){ + + fs.rmSync(`${jamfolder}/ports/${removablePort}`, { recursive: true, force: true }); + return true; + + } + else{ + + const newAppNames = appNames.filter((appName) => appName !== dirName) + fs.writeFileSync(`${jamfolder}/ports/${removablePort}`, newAppNames.join("\n")) + return false; + } + } + else{ + + return false; + } +} + +function killMosquitto(removablePort){ + + const jamfolder = getJamFolder() + if(fs.existsSync(`${jamfolder}/mqttpid/${removablePort}`)){ + const pid = fs.readFileSync(`${jamfolder}/mqttpid/${removablePort}`).toString().trim() + fs.rmSync(`${jamfolder}/mqttpid/${removablePort}`) + spawnSync('kill', ['-9' ,pid]); + } + else{ + console.log(body_sec_warning(`corrupted file directory,${removablePort} does not exist.`)) + } + + +} + +function killRedis(removablePort){ + const dport = Number(removablePort)+20000 + spawnSync('redis-cli', ['-p', dport, 'shutdown']); +} + +function cleanPort(removablePort,app,programName){ + const isPortStale = stalePort(removablePort,app,programName); + + if(isPortStale){ + killMosquitto(removablePort); + killRedis(removablePort); + return true + } + return false + + +} +function ArchiveLog(removablePort, appName, programName){ + + const [jamfolder,appfolder,folder] = getPaths(programName,appName) + + + + if(fs.existsSync(`${folder}/${removablePort}`)){ + + process.chdir(`${folder}/${removablePort}`); + const logs = fs.readdirSync('.').filter( (entry) => entry.includes("log")) + + if(!logs || logs.length === 0 ){ + process.chdir(`..`); + return + } + if(!fs.existsSync(`${folder}/log/${removablePort}`,{recursive: true})){ + fs.mkdirSync(`${folder}/log/${removablePort}`,{recursive: true}); + } + fs.writeFileSync(`${folder}/log/${removablePort}/log.c`,"---") + fs.writeFileSync(`${folder}/log/${removablePort}/log.j`,"---") + for(const log of logs){ + if(log.includes("j")){ + const data = fs.readFileSync(log) + fs.appendFileSync(`${folder}/log/${removablePort}/log.j`, data); + } + else{ + const workerNumber = log.split(".")[1]; + const data = fs.readFileSync(log) + fs.appendFileSync(`${folder}/log/${removablePort}/log.c`, `\nworker number ${workerNumber}:\n`); + fs.appendFileSync(`${folder}/log/${removablePort}/log.c`, data); + + } + } + + process.chdir(`..`); + + + } + +} +function cleanAppDir(removablePort,appName, programName){ + const [jamfolder,appfolder,folder] = getPaths(programName,appName) + if(fs.existsSync(`${folder}/${removablePort}`)){ + + try { + fs.rmSync(`${folder}/${removablePort}`, { recursive: true, force: true }); + } catch (error) { + } + return true; + } + return false; +} + + +export function cleanByPortNumber(programName, appName, PortNumber, NOVERBOSE=true){ + + + if(!programName || !appName || !PortNumber){ + if(!NOVERBOSE) + console.log("NO NEED FOR CLEANING") + return; + } + + + const tmuxIds = killtmux(PortNumber,appName ,programName); + if(!NOVERBOSE && tmuxIds) + console.log("Killed :", tmuxIds) + + const isPortCleaned = cleanPort(PortNumber,appName,programName); + if(!NOVERBOSE && isPortCleaned ){ + console.log("Redis and mosquitto on port ",PortNumber, "are removed" ) + } + ArchiveLog(PortNumber, appName, programName); + if(!NOVERBOSE ){ + console.log("All logs are archived for", `${programName.split(".")[0]}_${appName} on port:${PortNumber}` ) + } + const isDirCleaned = cleanAppDir(PortNumber, appName, programName); + if(!NOVERBOSE && isDirCleaned ){ + console.log(`port ${PortNumber} is cleaned for ${programName.split(".")[0]}_${appName}`) + } + +}; + +cleanByPortNumber("jt2", "shahin23",1885 ) diff --git a/tools/djam b/tools/djam index ec47bd77..7a82e408 100755 --- a/tools/djam +++ b/tools/djam @@ -51,7 +51,7 @@ params=$@ case $jcmd in list) - jamlist $params + djamlist $params ;; build) djambuild $params @@ -66,7 +66,7 @@ case $jcmd in djamtest $params ;; kill) - jamkill $params + djamkill $params ;; clean) jamclean $params diff --git a/tools/djambatch b/tools/djambatch new file mode 100755 index 00000000..b655905d --- /dev/null +++ b/tools/djambatch @@ -0,0 +1,583 @@ +#!/bin/bash + + +IDIR="${BASH_SOURCE%/*}" +if [[ ! -d "$IDIR" ]]; then IDIR="$PWD"; fi +#source "$IDIR/inc/pumba_tools.sh" +source "$IDIR/inc/mach_tools.sh" +source "$IDIR/inc/misc_tools.sh" +source "$IDIR/inc/docker_tools.sh" + + + +show_usage() { + cat << EOF +Runs the JAMScript executable (.jxe) in a Docker container. + +djamrun program.jxe +Runs J and C node, one each, of a device with program.jxe +under the application name 'app-N'. To run under a different +app name X, use the --app=X option. + +djamrun program.jxe --fog +Runs a fog node (only J node) with program.jxe. Similarly, the --cloud +flag runs a cloud node. + +By default, jamrun uses a Redis server running at 127.0.0.1:6379 as the +data store. The Redis server needs to be started before launching the +application. To use a different Redis server use the --data option. + +djamrun program.jxe --data=127.0.0.1:7000 +Runs program.jxe and connects it to an already running Redis server at +port 7000 of the local host. Redis server can run outside the +local host (Redis needs to the configured to accept outside +connections). + +To start more than one C node at a device use the following command. +djamrun program.jxe --num=4 + +To provide a set of tags to the program, use the following command. +djamrun program.jxe --tags="param1, param2" + +Use the --bg option to run a command in the backgroud. + +Usage: djamrun file.jxe [--app=appl_name] [--fog|--cloud] [--num=num_c_devs] + [--data=data-url] + [--tags=quoted_list_of_tags] + [--bg] + [--runon=container_to_run] + [--log] + [--loc] + [--link=random|near|best] + [--publish=dport:hport] + + +The djamrun command creates a run state in the $HOME/__jamrun folder. +EOF +} + + + +# runatcloud $dockid $file $jappid $data $tags +runatcloud() { + local dockid=$1 + local file=$2 + local appid=$3 + local data=$4 + local tags=$5 + + + argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " + if [ ! -z $log ]; then + argstr="$argstr --log" + fi + + buildjargs $argstr + + if [ -z $bg ]; then + echo "-" > $thisappfolder/$dockid/tmuxid + docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + else + echo $dockid > $thisappfolder/$dockid/tmuxid + tmux new-session -s $dockid"-j" -d docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + fi + +} + +# runatfog $dockid $file $jappid $data $tags +runatfog() { + local dockid=$1 + local file=$2 + local appid=$3 + local data=$4 + local tags=$5 + + argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " + if [ ! -z $log ]; then + argstr="$argstr --log" + fi + + buildjargs $argstr + + if [ -z $bg ]; then + echo "-" > $thisappfolder/$dockid/tmuxid + docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + else + echo $dockid > $thisappfolder/$dockid/tmuxid + tmux new-session -s $dockid"-j" -d docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + fi + +} + +# runatdevice $dockid $file $jappid $data $num $tags +runatdevice() { + local dockid=$1 + local file=$2 + local appid=$3 + local data=$4 + local num=$5 + local tags=$6 + + echo $num > $thisappfolder/$dockid/cdevs + echo "$dockid-c" > $thisappfolder/$dockid/tmuxid_c + + # save for short cut use + echo "$dockid-c" > $appfolder/tmuxid + + argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " + if [ ! -z $log ]; then + argstr="$argstr --log" + fi + + buildjargs $argstr + if [ -z $bg ]; then + echo "-" > $thisappfolder/$dockid/tmuxid + docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + else + echo $dockid"-j" > $thisappfolder/$dockid/tmuxid + tmux new-session -s $dockid"-j" -d docker exec -t --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + fi + echo ">>> Device started in container $dockid" +} + + +dojamrun() { + local type=$1 + local dockid=$2 + local file=$3 + local num=$4 + + save $type $thisappfolder/$dockid/machType + save $data $thisappfolder/$dockid/dataStore + save $dockerSer $thisappfolder/$dockid/dockerId + save "docker" $thisappfolder/$dockid/class + + case $type in + cloud) + runatcloud $dockid $file $jappid $data $tags + ;; + fog) + runatfog $dockid $file $jappid $data $tags + ;; + device) + runatdevice $dockid $file $jappid $data $num $tags + ;; + esac +} + + +# we generate a new app-XX only if the +# input is app-n, otherwise the jappid (output) is +# the input argument ($1) +getappid() { + local appid=$1 + local docki=$2 + + inc_counter $jamfolder/counter + count=$result + + if [ $appid == "app-n" ]; then + save_no_overwrite "app-"$count $thisappfolder/$docki/appid + else + save $appid $thisappfolder/$docki/appid + fi + + jappid=`cat $thisappfolder/$docki/appid` + + # save for short cut use + save "$jappid" $appfolder/appid +} + + +getdockerid() { + local rundock=$1 + + inc_counter $jamfolder/counter + local count=$result + dockerid="u-"$UID"-${type:0:3}-"$count + + if [ -z $rundock ] || [ `docker ps --filter id=$rundock | grep $rundock | wc -l | tr -d '[:space:]'` == "0" ]; then + result="new" + else + dockerSer=$rundock + result="old" + fi + +} + + +make_container() { + local type=$1 + local contname=$2 + + create_missingdir $jamfolder/$type + create_missingdir $jamfolder/$type/$contname + + if [ $type == "cloud" ]; then + startglobalmach $contname jamnet `cat $jamfolder/network` $dport $hport +# restartcloudpumba $contname + else + exit_missingfile $jamfolder/zones/count + local zcount=`cat $jamfolder/zones/count` + if [ -z $zcount ]; then + die "Zone count is undefined.. run djaminit again." + fi + local zone=$(( 1 + $RANDOM % $zcount )) + + startzonemach $zone $contname jamnet `cat $jamfolder/network` $dport $hport +# if [ $type == "fog" ]; then +# restartfogpumba $contname +# fi + fi + + save $result $jamfolder/$type/$contname/dockerId + save "1" $jamfolder/$type/$contname/refCount +} + +reuse_container() { + local type=$1 + local contname=$2 + + create_missingdir $jamfolder/$type + create_missingdir $jamfolder/$type/$contname + + inc_counter $jamfolder/$type/$contname/refCount +} + +createzonerouters() { + exit_missingfile $jamfolder/zones/count + + local zcount=`cat $jamfolder/zones/count` + + for i in `seq 1 $zcount`; do + startzonerouter $i "u-$UID-router-$i" jamnet `cat $jamfolder/network` +# restartrouterpumba "u-$UID-router-$i" + done +} + + +killdocker() { + local dock_id=$1 + + if [ -e $jamfolder/$type/$dock_id ]; then + dec_counter $jamfolder/$type/$dock_id/refCount + if [ $result == 0 ]; then + docker kill `cat $jamfolder/$type/$dock_id/dockerId` + docker rm $dock_id + fi + fi +} + + +removetmux() { + local tmid=$1 + + tmux has-session -t $tmid 2>/dev/null + local res=$? + if [ $res == "0" ]; then + tmux kill-session -t $tmid + fi +} + +removedockermach() { + + local tmid=`cat $thisappfolder/$dockerid/tmuxid` + removetmux $tmid + + if [ -e $thisappfolder/$dockerid/cdevs ]; then + local num=`cat $thisappfolder/$dockerid/cdevs` + for i in `seq 1 $num`; do + removetmux $tmid"-"$i + done + fi + + killdocker $dockerid + +} + + +processjxe() { + result="ok" +} + + +getportinfo() { + local pinfo=$1 + + dport="${pinfo%:*}" + hport="${pinfo##*:}" +} + + + +# Initialize all the option variables. +app=app-n +type=device +data=docker:6379 +tags= +num=1 +bg= +log= +runon= +link= +loc= +dport= +hport= +mount= + +file=$1 +shift +fext="${file##*.}" + +if [ -z $file ] || [ $file = "-h" ] || [ $file = "--help" ]; then + show_usage + exit 1 +fi + +if [ "$fext" != "jxe" ]; then + die "Extension on $file is not .jxe" +fi + + +while :; do + case $1 in + --help) + show_usage # Display a usage synopsis. + exit + ;; + --device_num=*) + device_num="${1#*=}" + shift + ;; + --app) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + app=$2 + shift + else + die 'ERROR: "--app" requires a non-empty option argument.' + fi + ;; + --app=?*) + app=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --app=) # Handle the case of an empty + die 'ERROR: "--app" requires a non-empty option argument.' + ;; + --runon) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + runon=$2 + shift + else + die 'ERROR: "--runon" requires a non-empty option argument.' + fi + ;; + --runon=?*) + runon=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --runon=) # Handle the case of an empty + die 'ERROR: "--runon" requires a non-empty option argument.' + ;; + --tags) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + tags=$2 + shift + else + die 'ERROR: "--tags" requires a non-empty option argument.' + fi + ;; + --tags=?*) + tags=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --tags=) # Handle the case of an empty + die 'ERROR: "--tags" requires a non-empty option argument.' + ;; + --num) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + num=$2 + shift + else + die 'ERROR: "--num" requires a non-empty option argument.' + fi + ;; + --num=?*) + num=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --num=) # Handle the case of an empty + die 'ERROR: "--num" requires a non-empty option argument.' + ;; + --data) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + data=$2 + shift + else + die 'ERROR: "--data" requires a non-empty option argument.' + fi + ;; + --data=?*) + data=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --data=) # Handle the case of an empty + die 'ERROR: "--data" requires a non-empty option argument.' + ;; + --loc) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + loc=$2 + shift + else + die 'ERROR: "--loc" requires longitude and lattitude specification' + fi + ;; + --loc=?*) + loc=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --loc=) # Handle the case of an empty + die 'ERROR: "--loc" requires longitude and lattitude specification' + ;; + --link) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + link=$2 + shift + else + die 'ERROR: "--link" requires a non-empty option argument.' + fi + ;; + --link=?*) + link=${1#*=} # Delete everything up to "=" and assign the remainder. + ;; + --link=) # Handle the case of an empty + die 'ERROR: "--link" requires a non-empty option argument.' + ;; + --publish) # Takes an option argument; ensure it has been specified. + if [ "$2" ]; then + getportinfo $2 + shift + else + die 'ERROR: "--publish" requires docker and port information' + fi + ;; + --publish=?*) + publish=${1#*=} # Delete everything up to "=" and assign the remainder. + getlonglat $publish + ;; + --publish=) # Handle the case of an empty + die 'ERROR: "--publish" requires docker and port information' + ;; + --fog) + if [ "$type" != "device" ]; then + die 'ERROR: "type" cannot be reassigned.' + else + type="fog" + num= + fi + ;; + --cloud) + if [ "$type" != "device" ]; then + die 'ERROR: "type" cannot be reassigned.' + else + type="cloud" + num= + fi + ;; + --log) + log=1 + ;; + --bg) + bg=1 + ;; + --mount) + mount=1 + ;; + --) # End of all options. + shift + break + ;; + -?*) + printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2 + ;; + *) # Default case: No more options, so break out of the loop. + break + esac + + shift +done + +# Check necessary parameters and set defaults + +if [ "$type" != "device" ] && [ -n "$num" ]; then + die "number of devices can't be speciied for fog/cloud" +fi + +if [ ! -z $mount ]; then + if [ -z ${JAMDATA} ]; then + echo "JAMDATA is not set. Set JAMDATA to the directory containing the datasets" + exit 1 + fi +fi + +# If docker is not installed, we fail here +check_prog docker "Docker not installed. Exiting." +#check_prog pumba "Pumba not installed. Download it from https://github.com/gaia-adm/pumba/releases" +check_prog tmux "tmux not installed. Exiting." + +# Check whether the global .jamruns folder is there +jamfolder=$HOME"/.jamruns" +exit_missingdir $jamfolder "__jamdir directory not found. Run djam pull first. " +exit_missingdir $jamfolder/zones "zones not setup. Run djam init first" +exit_missingfile $jamfolder/dockerImage "DockerImage not setup. Run djam pull first." + +#pumbastatus=`cat $jamfolder/pumba/status` + +appfolder=$jamfolder/apps +create_missingdir $appfolder + +if [ -e "$file" ]; then + + # Get the folder + filenoext="${file%.*}" + thisappfolder=$appfolder"/"$filenoext"_"$app + create_missingdir $thisappfolder + + # save for short cut use + save "$filenoext" $appfolder/program + save "$app" $appfolder/app + + # process the .jxe file + file=`pwd`/$file + processjxe $file + if [ $result != "ok" ]; then + die "Problem with JAMScript executable" + fi + + + dockerImage=`cat $jamfolder/dockerImage` + createzonerouters + createnetwork jamnet 10 $jamfolder + # cd into the $thisappfolder + cd $thisappfolder + + getdockerid $runon + docktype=$result + + create_missingdir $thisappfolder/$dockerid + getappid $app $dockerid + + if [ $docktype == "new" ]; then + # We are also putting resources such as redis on the container + make_container $type $dockerid + else + # Automatically inherit the redis.. no checking?? + reuse_container $type $dockerid + fi + docker exec $dockerSer mkdir /home/admin/temp + docker cp $file $dockerSer:/home/admin/temp/`basename $file` + + for ((i=1; i<=device_num; i++)); do + docker exec -t $dockerid jamrun /home/admin/temp/`basename $file` --bg $num + done + + if [ -z $bg ] && [ $docktype == "new" ]; then + removedockermach + fi +else + die "File: $file not found" +fi diff --git a/tools/djamkill b/tools/djamkill new file mode 100755 index 00000000..c9b32224 --- /dev/null +++ b/tools/djamkill @@ -0,0 +1,86 @@ +#!/bin/bash + +IDIR="${BASH_SOURCE%/*}" +if [[ ! -d "$IDIR" ]]; then IDIR="$PWD"; fi +source "$IDIR/inc/misc_tools.sh" + +die() { + printf '%s\n' "$1" >&2 + exit 1 +} + +show_usage() { + cat << EOF +A tool to display the active programs and their attributes. +Usage: djamlist + +djam list [--help] + +djam list [--all] + +djam list [--monitor] + +djam list [--remote] + +djam list [--type==fog] + +djam list [--dataStore==127.0.0.1:21883] + +djam list [--tmuxid==tg-25165] + +djam list [--port=3] + +djam list [--app==XX3] + +djam list [--prog==X] + +This is the docker version of jamlist. + +EOF +} + +run_djamkill() { + # Get a list of all running container IDs + local containers + containers=$(docker ps -q) + + if [[ -z "$containers" ]]; then + echo "No running Docker containers found." + exit 1 + fi + + for container in $containers; do + # Run djamlist in the container and capture its output. + # This assumes that "djamlist" when executed via docker exec returns the status only for that container. + jamlist_output=$(djamlist 2>/dev/null) + + # If the output might be aggregated, extract only the block for this container. + # The following awk command grabs lines after the "ContainerID: $container" line + # until the next "ContainerID:" header or the end of the output. + container_block=$(echo "$jamlist_output" | awk "/ContainerID: $container/{flag=1; next} /^ContainerID:/{flag=0} flag") + + # If the block shows no running instances, skip this container. + if echo "$container_block" | grep -q "No running instances of JAMScript."; then + continue + fi + + echo + echo "ContainerID: $container" + + # Run jamkill and capture its output. + output=$(docker exec -t "$container" jamkill 2>/dev/null) + + # Process each line, filtering out unwanted error messages. + while IFS= read -r line; do + if echo "$line" | grep -q -E "cannot access|no server running|\.jamruns/apps folder missing"; then + continue + fi + echo "$line" + done <<< "$output" + + docker stop "$container" + docker rm "$container" + done +} + +run_djamkill diff --git a/tools/djamlist b/tools/djamlist new file mode 100755 index 00000000..ae615137 --- /dev/null +++ b/tools/djamlist @@ -0,0 +1,115 @@ +#!/bin/bash + +IDIR="${BASH_SOURCE%/*}" +if [[ ! -d "$IDIR" ]]; then IDIR="$PWD"; fi +source "$IDIR/inc/misc_tools.sh" + +die() { + printf '%s\n' "$1" >&2 + exit 1 +} + +show_usage() { + cat << EOF +A tool to display the active programs and their attributes. +Usage: djamlist + +djam list [--help] + +djam list [--all] + +djam list [--monitor] + +djam list [--remote] + +djam list [--type==fog] + +djam list [--dataStore==127.0.0.1:21883] + +djam list [--tmuxid==tg-25165] + +djam list [--port=3] + +djam list [--app==XX3] + +djam list [--prog==X] + +This is the docker version of jamlist. + +EOF +} + +build_tmux_map() { + local appsfolder="$HOME/.jamruns/apps" + declare -gA TMUX_MAP + + for appdir in "$appsfolder"/*/; do + for instance in "$appdir"*/; do + if [ -d "$instance" ]; then + if [[ -f "$instance/class" && "$(tr -d '[:space:]' < "$instance/class")" == "docker" ]]; then + docker_id=$(tr -d '[:space:]' < "$instance/dockerId") + + if [ -f "$instance/tmuxid_c" ]; then + tmuxid=$(tr -d '[:space:]' < "$instance/tmuxid_c") + elif [ -f "$instance/tmuxid" ]; then + tmuxid=$(tr -d '[:space:]' < "$instance/tmuxid") + else + tmuxid="-" + fi + + TMUX_MAP["$docker_id"]="$tmuxid" + fi + fi + done + done +} + +run_djamlist() { + build_tmux_map # Build tmuxid map first + + # Get a list of running containers + local containers + containers=$(docker ps -q) + + # If no containers are running, exit + if [[ -z "$containers" ]]; then + echo "No running Docker containers found." + exit 1 + fi + + # Optional: Print headers if needed + echo + printf "%-15s %-10s %-15s %-12s %-12s %-15s %-8s %-10s %-20s %-s\n" \ + "CONTAINER-ID" "NAME" "PROGRAM" "HOST" "PARENT" "D-STORE" "TYPE" "C-NODES" "TMUX-ID" + printf '%*s\n' 125 '' | tr ' ' '-' + + # Process each container + for container in $containers; do + output=$(docker exec -t "$container" jamlist 2>/dev/null) + + # Clean output: + # 1. Remove blank lines + # 2. Remove internal headers + # 3. Remove separator lines + # 4. Capture last meaningful line only + last_line=$(echo "$output" | sed '/^$/d' | grep -v "^ID[[:space:]]\+NAME[[:space:]]\+PROGRAM" | grep -v '^-*$' | tail -n 1) + + # Skip if empty + if [[ -z "$last_line" ]]; then + continue + fi + + # Get mapped TMUX-ID (default to "-") + tmuxid="${TMUX_MAP[$container]:--}" + + # Extract columns + read -r ID NAME PROGRAM HOST PARENT DSTORE TYPE CNODES _ <<< "$last_line" + + # Final aligned output + printf "%-15s %-10s %-15s %-12s %-12s %-15s %-8s %-10s %-20s %-s\n" \ + "$container" "$NAME" "$PROGRAM" "$HOST" "$PARENT" "$DSTORE" "$TYPE" "$CNODES" "$tmuxid" + done +} + +run_djamlist + diff --git a/tools/djamlog b/tools/djamlog index ea9cec85..ddeb6fe0 100755 --- a/tools/djamlog +++ b/tools/djamlog @@ -123,15 +123,15 @@ if [ -e $appsfolder/$lprogram"_"$lapp ]; then runon=`cat $dir/dockerId` if [ -z $app ] && [ -z $program ]; then if [ -z $j ]; then - docker exec -it $runon jamlog + docker exec -t $runon jamlog else - docker exec -it $runon jamlog --j + docker exec -t $runon jamlog --j fi else if [ -z $j ]; then - docker exec -it $runon jamlog --program=$program --app=$app + docker exec -t $runon jamlog --program=$program --app=$app else - docker exec -it $runon jamlog --program=$program --app=$app --j + docker exec -t $runon jamlog --program=$program --app=$app --j fi fi fi diff --git a/tools/djamrun b/tools/djamrun index 8f53f837..eeebdc75 100755 --- a/tools/djamrun +++ b/tools/djamrun @@ -65,21 +65,21 @@ runatcloud() { local data=$4 local tags=$5 + echo "$dockid-j" > $thisappfolder/$dockid/tmuxid + echo "$dockid-j" > $appfolder/tmuxid - argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " + argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-j --tags=$tags --link=$link --loc=$loc " if [ ! -z $log ]; then argstr="$argstr --log" fi buildjargs $argstr - if [ -z $bg ]; then - echo "-" > $thisappfolder/$dockid/tmuxid - docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + docker exec -it $dockerSer tmux new-session -d -s "$dockid-j" "jamrun $file $results" else - echo $dockid > $thisappfolder/$dockid/tmuxid - tmux new-session -s $dockid"-j" -d docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + tmux new-session -s $dockid"-j" -d docker exec -it $dockerSer tmux new-session -d -s $dockid"-j" "jamrun $file $results" fi + echo ">>> Cloud started in container $dockid-j" } @@ -91,20 +91,21 @@ runatfog() { local data=$4 local tags=$5 - argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " + echo "$dockid-j" > $thisappfolder/$dockid/tmuxid + echo "$dockid-j" > $appfolder/tmuxid + + argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-j --tags=$tags --link=$link --loc=$loc " if [ ! -z $log ]; then argstr="$argstr --log" fi buildjargs $argstr - if [ -z $bg ]; then - echo "-" > $thisappfolder/$dockid/tmuxid - docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + docker exec -it $dockerSer tmux new-session -d -s "$dockid-j" "jamrun $file $results" else - echo $dockid > $thisappfolder/$dockid/tmuxid - tmux new-session -s $dockid"-j" -d docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + tmux new-session -s $dockid"-j" -d docker exec -it $dockerSer tmux new-session -d -s $dockid"-j" "jamrun $file $results" fi + echo ">>> Fog started in container $dockid-j" } @@ -117,11 +118,9 @@ runatdevice() { local num=$5 local tags=$6 - echo $num > $thisappfolder/$dockid/cdevs - echo "$dockid-c" > $thisappfolder/$dockid/tmuxid_c - - # save for short cut use - echo "$dockid-c" > $appfolder/tmuxid + echo $num > $thisappfolder/$dockid/cdevs + echo "$dockid-c" > $thisappfolder/$dockid/tmuxid_c + echo "$dockid-c" > $appfolder/tmuxid argstr=" --app=$appid --data=$data --num=$num --tmux=$dockid-c --tags=$tags --link=$link --loc=$loc " if [ ! -z $log ]; then @@ -129,14 +128,25 @@ runatdevice() { fi buildjargs $argstr - if [ -z $bg ]; then - echo "-" > $thisappfolder/$dockid/tmuxid - docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + if [ "$num" -gt 1 ]; then + # multiple C nodes + for i in $(seq 1 $num); do + if [ -z $bg ]; then + docker exec -it $dockerSer tmux new-session -d -s "$dockid-c-$i" "jamrun $file $results" + else + tmux new-session -s "$dockid-c-$i" -d docker exec -it $dockerSer tmux new-session -d -s "$dockid-c-$i" "jamrun $file $results" + fi + done else - echo $dockid"-j" > $thisappfolder/$dockid/tmuxid - tmux new-session -s $dockid"-j" -d docker exec -it --env NODE_PATH=/usr/local/lib/node_modules:/node_modules $dockerSer jamrun $file $results + # Single C node case + if [ -z $bg ]; then + docker exec -it $dockerSer tmux new-session -d -s "$dockid-c" "jamrun $file $results" + else + tmux new-session -s "$dockid-c" -d docker exec -it $dockerSer tmux new-session -d -s "$dockid-c" "jamrun $file $results" + fi fi - echo ">>> Device started in container $dockid" + echo ">>> Device started in container $dockid-c" + } @@ -204,7 +214,6 @@ getdockerid() { } - make_container() { local type=$1 local contname=$2 @@ -563,9 +572,9 @@ if [ -e "$file" ]; then # Automatically inherit the redis.. no checking?? reuse_container $type $dockerid fi - + docker exec $dockerSer mkdir -p /home/admin/temp docker cp $file $dockerSer:/home/admin/temp/`basename $file` - dojamrun $type $dockerid `basename $file` $num + dojamrun $type $dockerid /home/admin/temp/`basename $file` $num if [ -z $bg ] && [ $docktype == "new" ]; then removedockermach fi diff --git a/tools/djamterm b/tools/djamterm index d055fba6..087c3db9 100755 --- a/tools/djamterm +++ b/tools/djamterm @@ -44,7 +44,6 @@ Shows the J terminal of the program running under u-600-dev-2331. EOF } - localtmux() { local tmuxapp=$1 local termno=$2 @@ -60,37 +59,65 @@ localtmux() { fi } - dockertmux() { local tmuxapp=$1 local termno=$2 + local appsfolder="$HOME/.jamruns/apps" + + for appdir in "$appsfolder"/*/; do + for instance in "$appdir"*/; do + if [[ -f "$instance/class" && "$(tr -d '[:space:]' < "$instance/class")" == "docker" ]]; then + local docker_id + docker_id=$(tr -d '[:space:]' < "$instance/dockerId") + + # Check tmuxid_c (device C nodes) + if [[ -f "$instance/tmuxid_c" ]]; then + local dtm_c + dtm_c=$(tr -d '[:space:]' < "$instance/tmuxid_c") + if [[ "$dtm_c" == "$tmuxapp" ]]; then + # echo "Match found (Device). Attaching to $tmuxapp in $docker_id" + attach_tmux_in_docker "$docker_id" "$tmuxapp" "$termno" + return 0 + fi + fi - appsfolder=$HOME"/.jamruns/apps" - cd $appsfolder - - for jruns in */; do - if [ $jruns != "*/" ]; then - for jexs in `ls $appsfolder/$jruns`; do - dir=$appsfolder/$jruns$jexs - if [ -d $dir ] && [ -e $dir/class ]; then - local dcl=`cat $dir/class | tr -d '[:space:]'` - - if [ $dcl == "docker" ]; then - if [ -e $dir/tmuxid_c ]; then - local dtm=`cat $dir/tmuxid_c | tr -d '[:space:]'` - if [ $dtm == $tmuxapp ]; then - docker exec -ti `cat $dir/dockerId` script -q -c "/usr/bin/tmux attach -t $tmuxapp-$termno" /dev/null - break - fi - fi + # Check tmuxid (cloud/fog J nodes) + if [[ -f "$instance/tmuxid" ]]; then + local dtm_j + dtm_j=$(tr -d '[:space:]' < "$instance/tmuxid") + if [[ "$dtm_j" == "$tmuxapp" ]]; then + # echo "Match found (Cloud/Fog). Attaching to $tmuxapp in $docker_id" + attach_tmux_in_docker "$docker_id" "$tmuxapp" "$termno" + return 0 fi fi - done - fi + fi + done done + + # echo "No matching tmux session found for tmux-id: $tmuxapp" + return 1 } +attach_tmux_in_docker() { + local docker_id=$1 + local tmuxapp=$2 + local termno=$3 + + if [[ -t 1 ]]; then + if [ -z "$termno" ]; then + docker exec -it $docker_id tmux attach -t $tmuxapp + else + docker exec -it $docker_id tmux attach -t "$tmuxapp-$termno" + fi + else + echo "Tmux session '$tmuxapp' is running inside the container '$docker_id'." + echo "You can attach manually using:" + echo "docker exec -it $docker_id tmux attach -t $tmuxapp" + fi +} + ### # Main script execution begins here... # @@ -103,34 +130,31 @@ exit_missingdir $appsfolder ".jamruns/apps folder missing. JAMScript tools not s cd $appsfolder - if [ -z $1 ]; then if [ -e tmuxid ]; then tmuxid=`cat tmuxid` - dockertmux $tmuxid 1 - exit # this improves the readability of the script later - not needed! + dockertmux $tmuxid + exit fi else - # Show help if [ $1 == "-h" ] || [ $1 == "--help" ]; then show_usage - exit # readability improver! + exit elif [ $1 == "-t" ]; then if [ -e tmuxid ]; then tmuxid=`cat tmuxid` dockertmux $tmuxid $2 fi - exit # readability improver! + exit else if [ -z $2 ]; then txid=$1 - if [ ${txid: -1} == "c" ]; then - # Connect to the docker to display the C panes - dockertmux $txid 1 + if [[ ${txid: -1} == "c" || ${txid: -1} == "j" ]]; then + dockertmux $txid else localtmux $txid fi - exit # readability improver! + exit else if [ -n $3 ] && [ $2 == "-t" ]; then termid=$3 @@ -138,4 +162,4 @@ else fi fi fi -fi +fi \ No newline at end of file diff --git a/tools/file-jamrun-test.mjs b/tools/file-jamrun-test.mjs new file mode 100644 index 00000000..61696034 --- /dev/null +++ b/tools/file-jamrun-test.mjs @@ -0,0 +1,78 @@ +#!/usr/bin/env zx +import os from 'os'; +import process from 'process'; + +const TOTAL_REQUESTS = 75; +const CONCURRENCY = 5; +const FILE = 'jt1.jxe'; +const APP = 'DEMO'; +const BG = true; + +let active = 0; +let completed = 0; +let failed = 0; +let queue = []; +const checkpoints = []; +const requestDurations = []; + +console.time('Test Duration'); + +const runJamrun = async (i) => { + const args = ['jamrun.mjs', FILE, `--app=${APP}`]; + if (BG) args.push('--bg'); + + const start = Date.now(); + try { + await $`zx ${args}`; + const duration = Date.now() - start; + requestDurations[i] = duration; + console.log(`[${i}] Success`); + } catch (err) { + console.error(`[${i}] Failed: ${err.message}`); + failed++; + } finally { + completed++; + + if (completed % 10 === 0) { + const avgDuration = requestDurations + .slice(completed - 10, completed) + .reduce((a, b) => a + b, 0) / 10; + + const mem = process.memoryUsage(); + const cpu = os.loadavg()[0]; + + checkpoints.push({ + requests: completed, + avgDurationMs: avgDuration.toFixed(2), + memoryMB: (mem.rss / 1024 / 1024).toFixed(2), + cpuLoad: cpu.toFixed(2), + }); + } + } +}; + +const runTest = async () => { + for (let i = 0; i < TOTAL_REQUESTS; i++) { + const task = runJamrun(i); + queue.push(task); + + if (queue.length >= CONCURRENCY) { + await Promise.all(queue); + queue = []; + } + } + + await Promise.all(queue); // Finish remaining +}; + +await runTest(); +console.timeEnd('Test Duration'); + +console.log(`\nResults: ${completed} completed, ${failed} failed.`); + +// Output checkpoint table +console.log('\nCheckpoint Summary (Every 10 Requests)'); +console.log('Reqs\tAvg Time (ms)\tMemory (MB)\tCPU Load'); +checkpoints.forEach(cp => { + console.log(`${cp.requests}\t${cp.avgDurationMs}\t\t${cp.memoryMB}\t\t${cp.cpuLoad}`); +}); diff --git a/tools/file-monitor.sh b/tools/file-monitor.sh new file mode 100755 index 00000000..a3884378 --- /dev/null +++ b/tools/file-monitor.sh @@ -0,0 +1,40 @@ +#!/bin/bash + +# CONFIGURATION +TOTAL_MEM_THRESHOLD=6000 # Total system memory in MB +CHECK_INTERVAL=2 # Time between checks (in seconds) +LOG_FILE="filetest_monitor_alerts.log" +TEST_SCRIPT_NAME="file-jamrun-test.mjs" +AUTO_KILL=true + +echo "🛡️ Monitoring system memory during file-based JAMScript test..." +echo "Kill threshold: ${TOTAL_MEM_THRESHOLD}MB total system memory" +echo "Logging alerts to: $LOG_FILE" +echo "Auto-kill enabled: $AUTO_KILL" +echo "----------------------------------------------" + +while true; do + TEST_PID=$(pgrep -f "$TEST_SCRIPT_NAME") + + if [[ -z "$TEST_PID" ]]; then + echo "[$(date "+%Y-%m-%d %H:%M:%S")] $TEST_SCRIPT_NAME not running. Waiting..." | tee -a "$LOG_FILE" + sleep $CHECK_INTERVAL + continue + fi + + MEM_USED_MB=$(free -m | awk '/Mem:/ {print $3}') + + if [[ "$MEM_USED_MB" -ge "$TOTAL_MEM_THRESHOLD" ]]; then + TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S") + echo "[$TIMESTAMP] SYSTEM MEMORY ALERT: ${MEM_USED_MB}MB used." | tee -a "$LOG_FILE" + + if [[ "$AUTO_KILL" = true ]]; then + echo "[$TIMESTAMP] Killing test script (PID $TEST_PID)" | tee -a "$LOG_FILE" + kill -9 "$TEST_PID" && echo "[$TIMESTAMP] $TEST_SCRIPT_NAME killed." | tee -a "$LOG_FILE" + else + echo "[$TIMESTAMP] AUTO_KILL is disabled — not killing test." | tee -a "$LOG_FILE" + fi + fi + + sleep $CHECK_INTERVAL +done diff --git a/tools/fileDirectory.mjs b/tools/fileDirectory.mjs new file mode 100644 index 00000000..aaccc96f --- /dev/null +++ b/tools/fileDirectory.mjs @@ -0,0 +1,148 @@ +#!/usr/bin/env zx + +let HOME = os.homedir(); + +export function fileDirectorySetUp(file,app){ + const jamfolder=`${HOME}/.jamruns` + if(!fs.existsSync(jamfolder,{ recursive: true })){ + fs.mkdirSync(jamfolder) + } + if(!fs.existsSync(`${jamfolder}/ports`,{ recursive: true })){ + fs.mkdirSync(`${jamfolder}/ports`) + } + const appfolder=`${jamfolder}/apps`; + if(!fs.existsSync(appfolder,{ recursive: true })){ + fs.mkdirSync(appfolder) + } + const filenoext = path.basename(file, path.extname(file)); + const folder=`${appfolder}/${filenoext}_${app}` + if(!fs.existsSync(folder,{ recursive: true })){ + fs.mkdirSync(folder) + } + + fs.writeFileSync(`${appfolder}/program`, `${filenoext}\n`) + fs.writeFileSync(`${appfolder}/app`, `${app}\n`) + return [jamfolder,appfolder,folder,filenoext ] +} + +export function getJamFolder(){ + return `${HOME}/.jamruns` +} + +export function getAppFolder(){ + return `${HOME}/.jamruns/apps` +} + +export function getPaths(file,app){ + + const jamfolder=`${HOME}/.jamruns` + const appfolder=`${jamfolder}/apps`; + const filenoext = path.basename(file, path.extname(file)); + const folder=`${appfolder}/${filenoext}_${app}` + + return [jamfolder,appfolder,folder] +} + +export function getFolder(file,app){ + const jamfolder=`${HOME}/.jamruns` + const appfolder=`${jamfolder}/apps`; + const filenoext = path.basename(file, path.extname(file)); + const folder=`${appfolder}/${filenoext}_${app}` + + return folder; +} + +export function getFileNoext(file){ + return path.basename(file, path.extname(file)); +} + +export async function getAppFolderAndSubDir(){ + const jamfolder=`${HOME}/.jamruns` + const appfolder=`${jamfolder}/apps`; + if(!fs.existsSync(appfolder)){ + throw new Error("No running instances of JAMScript") + } + const subDirs = ((await fs.readdir(appfolder, { withFileTypes: true })).filter((entry) => entry.isDirectory())) + if(!subDirs || subDirs.lenth === 0 ){ + throw new Error("No running instances of JAMScript") + } + const subDirsName = subDirs.map(entry => entry.name ) + + return [subDirsName, appfolder] +} + + +export function getappid(mainf, localf, appid,appfolder){ + if(appid === "app-n"){ + //TODO: can be imporved by a try catch instead + let result; + if(fs.existsSync(`${mainf}/counter`)){ + let value = fs.readFileSync(`${mainf}/counter`); + result = Number(value.toString().trim()) + 1; + } + else{ + result = 1; + } + fs.writeFileSync(`${mainf}/counter`, `${result}\n`) + fs.writeFileSync(`${localf}/appid`, `app-${result}\n`) + } + else{ + fs.writeFileSync(`${localf}/appid`,`${appid}`) + } + const jappid = fs.readFileSync(`${localf}/appid`) + fs.writeFileSync(`${appfolder}/appid`,`${jappid}`) + return jappid; +} + +export function isValidExecutable(){ + if(!fs.existsSync(`jstart.js`)) + throw new Error("jstart.js is missing") + + if(!fs.existsSync(`jamout.js`)) + throw new Error("jamout.js is missing") + + if(!fs.existsSync(`a.out`)) + throw new Error("a.out is missing") + + if(!fs.existsSync(`MANIFEST.txt`)) + throw new Error("MANIFEST.txt is missing") + +} + +export async function cleanExecutables(){ + if(fs.existsSync(`jstart.js`)) + await fs.unlink("jstart.js") + + if(fs.existsSync(`jamout.js`)) + await fs.unlink("jamout.js") + + if(fs.existsSync(`a.out`)) + await fs.unlink("a.out") + + +} + +export function fileDirectoryMqtt(folder, iport,jamfolder,app){ + if(!fs.existsSync(`${jamfolder}/mqttpid`)){ + fs.mkdirSync(`${jamfolder}/mqttpid`); + } + fs.writeFileSync(`${folder}/${iport}/mqtt.conf`, "#\n"); + fs.appendFileSync(`${folder}/${iport}/mqtt.conf`, "allow_anonymous true\n"); + fs.appendFileSync(`${folder}/${iport}/mqtt.conf`, "#\n"); + fs.appendFileSync(`${folder}/${iport}/mqtt.conf`, `listener ${iport}\n`); + const dirName = folder.split("/").pop() + if(fs.existsSync(`${jamfolder}/ports/${iport}`)){ + const dirNames = fs.readFileSync(`${jamfolder}/ports/${iport}`).toString().trim().split("\n") + if(!dirNames.includes(dirName)){ + fs.appendFileSync(`${jamfolder}/ports/${iport}`, `\n${dirName}\n`) + } + + } + else{ + + fs.writeFileSync(`${jamfolder}/ports/${iport}`, `${dirName}\n`) + } + + +} + diff --git a/tools/filetest_monitor_alerts.log b/tools/filetest_monitor_alerts.log new file mode 100644 index 00000000..873fd55e --- /dev/null +++ b/tools/filetest_monitor_alerts.log @@ -0,0 +1,29 @@ +[2025-03-30 12:36:41] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:36:43] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:36:45] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:36:47] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:36:49] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:36:51] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:40] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:42] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:44] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:46] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:48] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:50] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:52] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:54] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:56] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:37:58] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:01] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:03] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:05] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:07] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:09] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:11] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:13] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:15] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:17] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:19] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:21] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:23] file-jamrun-test.mjs not running. Waiting... +[2025-03-30 12:38:25] file-jamrun-test.mjs not running. Waiting... diff --git a/tools/inc/mach_tools.sh b/tools/inc/mach_tools.sh index 7841817a..165d4a7c 100644 --- a/tools/inc/mach_tools.sh +++ b/tools/inc/mach_tools.sh @@ -79,6 +79,9 @@ startzonemach() { count=$(( $newcount + 1 )) fi + # Remove existing container with same name if it exists + docker rm -f $machname 2>/dev/null + echo "Machine: " $machname " starting with IP: " 10.$subnet.$zonenum.$count # Create the machine @@ -134,6 +137,9 @@ startglobalmach() { count=$(( $newcount + 1 )) fi + # Remove existing container with same name if it exists + docker rm -f $machname 2>/dev/null + # Create the machine if [ -z $dport ] && [ -z $hport ]; then if [ -z $mount ]; then diff --git a/tools/inventory.ini b/tools/inventory.ini new file mode 100644 index 00000000..beb80df7 --- /dev/null +++ b/tools/inventory.ini @@ -0,0 +1,7 @@ +[servers] +server2 ansible_host=10.140.16.106 ansible_user=jamtools +server3 ansible_host=10.140.16.107 ansible_user=jamtools +server4 ansible_host=10.140.16.108 ansible_user=jamtools + +[all:vars] +ansible_python_interpreter=/usr/bin/python3 diff --git a/tools/jambatch-playbook.yml b/tools/jambatch-playbook.yml new file mode 100644 index 00000000..e9131008 --- /dev/null +++ b/tools/jambatch-playbook.yml @@ -0,0 +1,13 @@ +- name: Run JamBatch command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run batch command and store logs + shell: zx wrapper.mjs djambatch "{{ file }}" "{{ deviceNb }}" "{{ app }}" --bg --serverIP={{ ansible_host }} > jambatch.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jambatch.mjs b/tools/jambatch.mjs new file mode 100755 index 00000000..1ac04540 --- /dev/null +++ b/tools/jambatch.mjs @@ -0,0 +1,159 @@ +#!/usr/bin/env zx +import {getBatchArgs} from './parser.mjs' +import { spawnSync } from 'child_process'; + + +import { + body_1, + header_1, + header_2, + body_sec, + body_2, + body_sec_warning, + body_2_bold, +} from "./chalk.mjs"; +let args; + +function show_usage() { + const usageMessage = ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jambatch`)}${body_1( + ` -- a tool to run JXE files in batch` + )} + + ${header_1(`SYNOPSIS`)} + + Usage: jambatch + + [--help] + [--fog = ${body_sec(`numProgram1-programName1,numProgram2-programName2`)}] + [--device] = ${body_sec(`numProgram1-programName1,numProgram2-programName2`)}] + [--cloud] = ${body_sec(`numProgram1-programName1,numProgram2-programName2`)}] + [--cFile = ${body_sec(`cloudProg1File,cloudProg2File`)}] + [--fFile = ${body_sec(`fogProg1File,fogProg2File`)}] + [--dFile = ${body_sec(`deviceProg1File,deviceProg2File`)}] + [--num = ${body_sec(`cNumProg1,CnumProg2`)}] + [--cLoc = ${body_sec(`longCloudProg1,latCloudProg1-longCloudProg2-latCloudProg2`)}] + [--fLoc = ${body_sec(`longFogProg1,latFogProg1-longFogProg2-latFogProg2`)}] + [--dLoc = ${body_sec(`longDeviceProg1,latDeviceProg1-longDeviceProg2-latDeviceProg2`)}] + [--cEdge= ${body_sec(`numEdgeCloudProg1,numEdgeCloudProg2`)}] + [--fEdge= ${body_sec(`numEdgeFogProg1,numEdgeFogProg2`)}] + [--dEdge= ${body_sec(`numEdgeDeviceProg1,numEdgeDeviceProg2`)}] + + ${header_1(`DESCRIPTION`)} + + + --- jambatch.mjs --help + ${body_2("--help : use this flag to display this usage message.")} + + --- jambatch.mjs program.jxe --fog=2-XX,3-X --fFile=1-jt2.jxe,2-jt3.jxe,2-jt4.jxe [--fLoc=300,300-400,400] [fEdge=1] + ${body_2_bold(`note: --fog and fFilen prefix numbers should add up to the same number. ex)2+3 = 1+2+2.`)} + ${body_2("the command abouve executes the following commands synchronously:")} + ${body_2(`jamrun.mjs jt2.jxe --app=XX --loc=300,300 --edge=1 --bg --log --fog`)} + ${body_2(`jamrun.mjs jt3.jxe --app=XX --loc=400,400 --bg --log --fog`)} + ${body_2(`jamrun.mjs jt3.jxe --app=X --bg --log --fog`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --fog`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --fog`)} + + + --- jambatch.mjs program.jxe --cloud=2-XX,3-X --cFile=1-jt2.jxe,2-jt3.jxe,2-jt4.jxe [--cLoc=300,300-400,400] [cEdge=1] + ${body_2_bold(`note: --cloud and cFilen prefix numbers should add up to the same number.ex) 2+3 = 1+2+2.`)} + ${body_2("the command abouve executes the following commands synchronously:")} + ${body_2(`jamrun.mjs jt2.jxe --app=XX --loc=300,300 --edge=1 --bg --log --cloud`)} + ${body_2(`jamrun.mjs jt3.jxe --app=XX --loc=400,400 --bg --log --cloud`)} + ${body_2(`jamrun.mjs jt3.jxe --app=X --bg --log --cloud`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --cloud`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --cloud`)} + + --- jambatch.mjs program.jxe --device=2-XX,3-X --dFile=1-jt2.jxe,2-jt3.jxe,2-jt4.jxe [--dLoc=300,300-400,400] [dEdge=1] [num=2,3,1] + ${body_2_bold(`note: --cloud and cFilen prefix numbers should add up to the same number.ex) 2+3 = 1+2+2.`)} + ${body_2("the command abouve executes the following commands synchronously:")} + ${body_2(`jamrun.mjs jt2.jxe --app=XX --loc=300,300 --edge=1 --bg --log --device --num=2`)} + ${body_2(`jamrun.mjs jt3.jxe --app=XX --loc=400,400 --bg --log --device --num=3`)} + ${body_2(`jamrun.mjs jt3.jxe --app=X --bg --log --device --num=1`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --device`)} + ${body_2(`jamrun.mjs jt4.jxe --app=X --bg --log --device`)} + + + ${header_2( + `1) The --bg and --log flags are always set using jambatch.mjs.` + )} + ${header_2( + `2) No possibility running remote jobs using batch mode.` + )} + `; + + console.log(usageMessage); +} + +try { + args = getBatchArgs(process.argv); +} catch (error) { + console.log(show_usage()) + error.message === "SHOW USAGE" ? null : console.log(error); + process.exit(1); +} +let spawnPipe = 'inherit' +if(args.config){ + const jsonString = fs.readFileSync(args.config); + const jobs = JSON.parse(jsonString).jobs; + + if(!args.verb){ + spawnPipe = ['ignore', 'ignore', 'inherit'] + + } + for(let i = 0 ; i < jobs.length ; i++){ + if(!jobs[i].name){ + if(args.verb){ + console.log(body_sec_warning(`Warning: job number ${i+1} is missing name, it will be skipped`)) + } + continue; + } + if(!jobs[i].file){ + if(args.verb){ + console.log(body_sec_warning(`Warning: job number ${i+1} is missing file name, it will be skipped`)) + } + continue; + } + if(!jobs[i].type){ + if(args.verb){ + console.log(body_sec_warning(`Warning: job type missing, it will be skipped`)) + } + continue; + } + + const exec = `jamrun.mjs ${jobs[i].file} --app=${jobs[i].name} --bg --log --${jobs[i].type}` + if(jobs.num) + exec + ` --num=${jobs.num}` + if(jobs.loc) + exec + ` --num=${jobs.loc}` + if(jobs.edge) + exec + ` --num=${jobs.edge}` + if(jobs.verb) + exec + ` --verb` + + + if(args.verb){ + console.log(`${body_sec(`Starting job number: ${i+1} - ${exec}`)}`) + } + + spawnSync('zx', [exec], { + stdio: spawnPipe, + shell: true + }); + } + process.exit(0) +} + +const verb = args.pop() + +for(let arg of args){ + if(verb){ + console.log(`${body_sec(`Starting new job: jamrun.mjs ${arg}`)}`) + } + spawnSync('zx', ['jamrun.mjs'].concat(arg), { + stdio: spawnPipe, + shell: true + }); +} diff --git a/tools/jamclean.mjs b/tools/jamclean.mjs new file mode 100755 index 00000000..06d80dc6 --- /dev/null +++ b/tools/jamclean.mjs @@ -0,0 +1,453 @@ +#!/usr/bin/env zx + +import { getAppFolder, getJamFolder } from "./fileDirectory.mjs"; +const { spawnSync } = require('child_process'); +import { cleanByPortNumber } from "./cleanUp.mjs"; +import { dirname, resolve } from 'path'; +import { fileURLToPath } from 'url'; +import { Client } from 'ssh2'; + + +const p1 = spawnSync('which', ['tmux']); +const TMUX = p1.stdout.toString().trim() +const __filename = fileURLToPath(import.meta.url) +const __dirname = dirname(__filename); +const jamcKillPath = resolve(__dirname, 'jamkill.mjs'); + +const p = spawnSync('which', ['mosquitto_pub']); +const MOSQUITTO_PUB = p.stdout.toString().trim() + +function getRunningDirs(){ + const appFolder = getAppFolder() + const appToPort = new Map() + const activePorts = fs.readdirSync(`${appFolder}`) + for(let port of activePorts){ + const apps = fs.readFileSync(`${appFolder}/${port}`).toString().trim().split("\n"); + for(let app of apps){ + if(appToPort.has(app)){ + const portList = appToPort.get(app); + portList.push(port) + appToPort.set(app,portList) + } + else{ + appToPort.set(app,[port]) + } + } + } + return appToPort; +} + +function dirNameToAppName(dirName){ + const dir = dirName.split('_') + if(dir.length > 2){ + return (dir.filter((_,index) => index !== 0)).join("_") + } + else{ + return dir[1]; + } + +} +function dirNameToProgramName(dirName){ + return (dirName.split('_'))[0] +} + + +async function isJamrunRunning(dir,portNum){ + const appFolder = getAppFolder() + const myAppDir = dir; + //should be string. + const myAppPortNum = portNum; + const shellPIDpath = `${appFolder}/${myAppDir}/${myAppPortNum}/shellpid` + + if(!fs.existsSync(`${shellPIDpath}`)){ + return false; + } + const pid = fs.readFileSync(`${shellPIDpath}`).toString().trim(); + let running; + try{ + const p = await $`ps -p ${pid} | grep jamrun | wc -l | tr -d '[:space:]'` + running = Number(p.stdout.toString().trim()) + } + catch(error){ + return false + } + if(!running){ + return false + } + return pid; +} + +async function isJfileRunning(dir,portNum){ + const appFolder = getAppFolder() + const myAppDir = dir; + const myAppPortNum = portNum; + const processId = `${appFolder}/${myAppDir}/${myAppPortNum}/processId` + + //make sure j file is getting the time to write to filedirectory + + if(!fs.existsSync(`${processId}`)){ + return false; + } + let pid = fs.readFileSync(`${processId}`).toString().trim(); + if(pid === "new"){ + return false; + } + let running; + try{ + const p = await $`ps -p ${pid} | grep node | wc -l | tr -d '[:space:]'` + running = Number(p.stdout.toString().trim()); + } + catch(error){ + return false; + } + if(!running){ + return false; + } + return pid; +} + + +async function isMosquittoRunning(port){ + try{ + await $`${MOSQUITTO_PUB} -p ${port} -t "test" -m "hello"`.quiet(); + return true; + } + catch(error){ + return false; + } +} + +async function isCfileRunning(Dir,port,num){ + const myAppDir = Dir; + const portNum = port; + const workerNum = num; + const appFolder = getAppFolder() + const cdevID = `${appFolder}/${myAppDir}/${portNum}/cdevProcessId.${workerNum}` + + if(!fs.existsSync(`${cdevID}`)){ + return false; + } + const pid = fs.readFileSync(`${cdevID}`).toString().trim(); + let running; + try{ + const p = await $`ps -p ${pid} | grep a.out | wc -l | tr -d '[:space:]'` + running = Number(p.stdout.toString().trim()); + } + catch(error){ + return false; + } + if(!running){ + return false; + } + return pid; +} +async function isDevice(Dir,port){ + const appFolder = getAppFolder(); + const appDir = Dir; + const portNum = port; + const machType = `${appFolder}/${appDir}/${portNum}/machType` + if(!fs.existsSync(`${machType}`)){ + return false; + } + const type = fs.readFileSync(`${machType}`).toString().trim() + if(type === "device"){ + return true + } + return false; +} + +async function getRunningCfiles(Dir,port){ + const appFolder = getAppFolder(); + const appDir = Dir; + const portNum = port; + const runningCfiles = [] + const portDir = `${appFolder}/${appDir}/${portNum}` + if(!fs.existsSync(portDir)){ + return; + } + const cfilesNum = ((fs.readdirSync(portDir)).filter((entry) => entry.includes("cdevProcessId"))).map((entry) => entry.split(".")[1]) + for(let cfileNum of cfilesNum){ + if(await isCfileRunning(appDir,portNum,cfileNum)){ + runningCfiles.push(`${cfileNum}`) + } + + } + return runningCfiles; +} + +function cleanCfiles(portDir, currCfile){ + const oldCdevs = (fs.readdirSync(portDir)).filter((entry) => entry.includes("cdev")) + const genericTag = fs.readFileSync(`${portDir}/tmuxid`).toString().trim() + if( (oldCdevs.length)*2 === currCfile.length){ + return; + } + for(let oldCdev of oldCdevs){ + const cNum = oldCdev.split(".")[1]; + if(!currCfile.includes(cNum)){ + const id = genericTag+`-${cNum}` + try{ + fs.unlinkSync(`${portDir}/${oldCdev}`); + spawnSync(TMUX, ['kill-session', '-t', id]); + } + catch(error){ + + } + + } + } +} +function cleanPorts(AppToRemove){ + const jamFolder = getJamFolder() + for(let port of AppToRemove.keys()){ + if(!fs.existsSync(`${jamFolder}/ports/${port}`)){ + continue; + } + const oldApss = fs.readFileSync(`${jamFolder}/ports/${port}`).toString().trim().split("\n") + const toRemove = AppToRemove.get(port) + const newApps = oldApss.filter((entry) => !toRemove.includes(entry)) + if(newApps.length === 1){ + fs.writeFileSync(`${jamFolder}/ports/${port}`, `${newApps[0]}`) + + } + else{ + fs.writeFileSync(`${jamFolder}/ports/${port}`, `${newApps.join("\n")}`) + } + + } +} + +async function clean(){ + const AppToRemove = new Map(); + const jamFolder = getJamFolder() + const portsDir = `${jamFolder}/ports` + const appFolder = getAppFolder() + if(!fs.existsSync(portsDir)){ + return; + } + const ports = fs.readdirSync(portsDir) + if(ports.length === 0 ){ + return + } + portLoop: + for(let port of ports){ + if(!fs.existsSync(`${portsDir}/${port}`)){ + continue; + } + const dirs = fs.readFileSync(`${portsDir}/${port}`).toString().trim().split("\n") + for(let dir of dirs){ + //mosquitto not running kill + if(!await isMosquittoRunning(port) && port){ + await $`zx ${jamcKillPath} --port==${port}` + continue portLoop; + } + //jFile is not running. to remove fromport list + if(!(await isJamrunRunning(dir,port)) && !(await isJfileRunning(dir,port))){ + const programName = dirNameToProgramName(dir)+".jxe"; + const appName = dirNameToAppName(dir); + cleanByPortNumber(programName, appName, port); + if(AppToRemove.has(port)){ + const dummy = AppToRemove.get(port); + dummy.push(dir); + AppToRemove.set(port,dummy) + } + else{ + AppToRemove.set(port,[dir]) + } + } + //It's running and files are uptodate, update Cnum and clean cdevs + if((await isJfileRunning(dir,port)) && (await isDevice(dir,port))){ + const Cfiles = await getRunningCfiles(dir,port); + const numCnodes = Cfiles.length + if(!fs.existsSync(`${appFolder}/${dir}/${port}/numCnodes`)){ + fs.writeFileSync(`${appFolder}/${dir}/${port}/numCnodes`,`${numCnodes}`) + continue; + } + const numCnodeFile = Number(fs.readFileSync(`${appFolder}/${dir}/${port}/numCnodes`).toString().trim()) + if(numCnodeFile !== numCnodes){ + fs.writeFileSync(`${appFolder}/${dir}/${port}/numCnodes`,`${numCnodes}`) + } + cleanCfiles(`${appFolder}/${dir}/${port}`, Cfiles) + } + + } + } + cleanPorts(AppToRemove) +} + + + + +function getRemoteapps(){ + const jamfolder = getJamFolder() + const myMap = new Map() + if(!fs.existsSync(`${jamfolder}/remote`)){ + return null + } + const remoteMachines = fs.readdirSync(`${jamfolder}/remote`) + for(let remoteMachine of remoteMachines){ + const ports = fs.readdirSync(`${jamfolder}/remote/${remoteMachine}`) + let arg='' + for(let port of ports){ + const apps = fs.readFileSync(`${jamfolder}/remote/${remoteMachine}/${port}`).toString().trim().split("\n") + for(let app of apps){ + arg = arg+app+":"+port+"##" + } + } + const result = arg.slice(0, -2); + myMap.set(remoteMachine,result) + } + + return myMap; +} +async function makeConnection(config){ + return await new Promise((resolve, reject) => { + const client = new Client(); + client.on('ready', () => { + resolve(client); + }); + + client.on('error', (error) => { + reject(error); + }); + + client.connect(config); + }); +} +async function executeScript(client, command){ + return (await new Promise((resolve, reject) =>{ + client.exec(command, (err,stream) =>{ + + if (err) console.log(error); + let result = ''; + stream.on("close", () => { + resolve(result) + }) + stream.on("data" , (data) =>{ + + if(data.includes("TOREMOVE:")){ + let rm = data.toString().split(":")[1] + result = result + rm + } + }) + }) + })) +} +// main() +async function cleanRemote(toRemove){ + const jamfolder = getJamFolder() + + + for(let machine of toRemove.keys()){ + for(let rm of toRemove.get(machine)){ + + const dir = rm.split("/")[0] + const port = rm.split("/")[1] + if(!port){ + fs.rmSync(`${jamfolder}/remote/${machine}`, { recursive: true, force: true }); + } + if(!fs.existsSync(`${jamfolder}/remote/${machine}/${port}`)){ + return + } + const apps = fs.readFileSync(`${jamfolder}/remote/${machine}/${port}`).toString().trim().split("\n"); + const currApps = apps.filter((entry)=>(!entry.includes(dir))); + + if(currApps.length === 0 ){ + fs.rmSync(`${jamfolder}/remote/${machine}/${port}`, { recursive: true, force: true }); + } + else{ + const toWrite = currApps.join("\n") + fs.writeFileSync(`${jamfolder}/remote/${machine}/${port}`,`${toWrite}\n`) + } + } + if((fs.readdirSync(`${jamfolder}/remote/${machine}`)).length === 0 ){ + fs.rmSync(`${jamfolder}/remote/${machine}`, { recursive: true, force: true }); + } + } +} + +(async () =>{ + const arg = process.argv.filter((entry) => (!entry.includes('node') && !entry.includes('zx') && !entry.includes('jamclean.mjs'))); + const appfolder = getAppFolder(); + const jamFolder = getJamFolder(); + if(arg.length === 0){ + let currIP ; + if (os.platform() === 'win32') { + currIP = (await $`powershell (Get-NetIPAddress -AddressFamily IPv4).IPAddress`.catch(() => '')).toString().trim(); + } else if (os.platform() === 'darwin') { + currIP = (await $`ipconfig getifaddr en0`.catch(() => '')).toString().trim(); + } else if (os.platform() === 'linux') { + currIP = (await $`hostname -I`.catch(() => '')).toString().trim(); + } + const map = getRemoteapps(); + + const removalMap = new Map() + if(map){ + for(let machines of map.keys()){ + const [host,port] = machines.split("_"); + const arg = map.get(machines); + const config = { + host: host, + port: port, + username: 'admin', + password: 'admin' + }; + let client + try{ + client = await makeConnection(config); + } + catch(error){ + fs.rmSync(`${jamFolder}/remote/${machines}`, { recursive: true, force: true }); + continue; + } + + const pathExport ="export PATH=$PATH:/home/admin/JAMScript/node_modules/.bin" + const changeDir= "cd JAMScript/tools" + const script = `jamclean.mjs --root=${currIP} --hash=${arg}` + const result = await executeScript(client,`${pathExport} && ${changeDir} && ${script}`) + const toRemove = result.trim().split("\n"); + if(toRemove.length !==0 && toRemove[0] !== ''){ + removalMap.set(machines,toRemove) + } + + } + + cleanRemote(removalMap) + } + } + await clean() + + if(arg.length === 2){ + const rootIP = (arg[0].split("="))[1] + const hash = (arg[1].split("="))[1] + + const portDirs = hash.split("##") + for(let portDir of portDirs){ + let dirName = portDir.split(":")[0] + let portName = portDir.split(":")[1] + if(!fs.existsSync(`${jamFolder}/ports/${portName}`)){ + console.log(`TOREMOVE:${dirName}/${portName}`); + await sleep(5) + continue + }; + const running = fs.readFileSync(`${jamFolder}/ports/${portName}`).toString().trim(); + if(!running.includes(dirName)){ + console.log(`TOREMOVE:${dirName}/${portName}`); + await sleep(5) + continue + }; + if(!fs.existsSync(`${appfolder}/${dirName}/${portName}/root`)){ + console.log(`TOREMOVE:${dirName}/${portName}`); + await sleep(5) + continue + }; + const dirRoot = fs.readFileSync(`${appfolder}/${dirName}/${portName}/root`).toString().trim() + if(rootIP !== dirRoot){ + console.log(`TOREMOVE:${dirName}/${portName}`); + await sleep(5) + continue + }; + } + } + process.exit() + +})(); \ No newline at end of file diff --git a/tools/jamkill b/tools/jamkill index b85b2f02..221aa4c4 100755 --- a/tools/jamkill +++ b/tools/jamkill @@ -79,9 +79,9 @@ killprocess() { local didp=`cat $1/dockerId` local present=`docker ps --filter id=$didp | grep $didp | wc -l | tr -d '[:space:]'` if [ $present == "1" ]; then - docker exec -it $didp jamkill `cat $1/appid` + docker exec -t $didp jamkill `cat $1/appid` echo "-" > $1/dockerId - local count=`docker exec -it $didp jamlist | wc -l | tr -d '[:space:]'` + local count=`docker exec -t $didp jamlist | wc -l | tr -d '[:space:]'` if (( $count <= 2 )); then echo "Killing docker $didp" docker kill $didp diff --git a/tools/jamkill-playbook.mjs b/tools/jamkill-playbook.mjs new file mode 100644 index 00000000..edc094ed --- /dev/null +++ b/tools/jamkill-playbook.mjs @@ -0,0 +1,13 @@ +- name: Run JAMKill command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run kill command and store logs + shell: zx wrapper.mjs jamkill --serverIP={{ ansible_host }} > jamkill.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamkill-playbook.yml b/tools/jamkill-playbook.yml new file mode 100644 index 00000000..0a7a78ff --- /dev/null +++ b/tools/jamkill-playbook.yml @@ -0,0 +1,13 @@ +- name: Run JAMKill command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run kill command and store logs + shell: zx wrapper.mjs jamkill --serverIP={{ ansible_host }} > jamkill.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools \ No newline at end of file diff --git a/tools/jamkill.mjs b/tools/jamkill.mjs new file mode 100755 index 00000000..2323f1bc --- /dev/null +++ b/tools/jamkill.mjs @@ -0,0 +1,426 @@ +#!/usr/bin/env zx + +import { getAppFolder, getJamFolder } from "./fileDirectory.mjs"; +import {getKilltArgs} from "./parser.mjs" +import { cleanByPortNumber} from "./cleanUp.mjs"; +import { Client } from 'ssh2'; +import { header_1,header_2 , body_2_line , body_1, body_sec, keyWord, body_2,body_2_bold, body_sec_warning } from "./chalk.mjs"; + +let currIP; +if (os.platform() === "win32") { + currIP = ( + await $`powershell (Get-NetIPAddress -AddressFamily IPv4).IPAddress`.catch( + () => "" + ) + ) + .toString() + .trim(); +} else if (os.platform() === "darwin") { + currIP = (await $`ipconfig getifaddr en0`.catch(() => "")) + .toString() + .trim(); +} else if (os.platform() === "linux") { + currIP = (await $`hostname -I`.catch(() => "")).toString().trim(); +} + +function show_usage(){ + const usageMessage = + ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamkill`)}${body_1(` -- a tool to kill one or more running JXE files.`)} + + ${header_1(`SYNOPSIS`)} + + Usage: jamkill + [--reset] + [--help] + [--all] + [--remote=${body_sec(`IPAddress`)}] + [--app==${body_sec(`appName`)}] + [--prog==${body_sec(`programName`)}] + [--port==${body_sec(`portNum`)}] + + ${header_1(`DESCRIPTION`)} + + --- ${keyWord('jamkill')} by default kills all the running local apps. + + --- jamkill [--reset] + ${body_2(`Use this flag to kill all the running programs and remove appfolder, port directory and mqttPID directory. + it's useful for the cases that either the file directory is corrupted or a fresh start is required.`)} + ${body_2_bold(`NOTE: + The only usable flag is next to --reset flag is --remote otherwise, + --reset flag will disable all the other flags and do a hard reset.`)} + + --- jamkill [--help] + ${body_2(`Use this flag to display this usage msg.`)} + + --- jamkill [--all] + ${body_2(`Use this flag to kill all the running apps.`)} + ${body_2_bold(`NOTE: + 1) If --all used next to the --reset flag. --all will be disabled. + 2) If --all used with --all flag --app, --prog, --port, they will be disabled.`)} + + --- jamkill [--remote] + ${body_2(`Use this flag to kill the executions as well as local ones.`)} + ${body_2_bold(`NOTE: + jamkill --remote only kills the remote programs which are started by the local machine running jamkill.`)} + + --- jamkill [--app==X] + ${body_2(`Use this flag to kill a program with a specific appName.`)} + + --- jamkill [--prog==X] + ${body_2(`Use this flag to kill a program with a specific programName.`)} + + --- jamkill [--port=3] + ${body_2(`Use this flag to kill a program running on a certain port.`)} + + NOTE: + ${body_2(`1) --app & --prog & --port can be used all together or two by two to select the programs to be killed.`)} + ${body_2(`2) To set --app , --prog and --port options two equal signs has to be used.`)} + + + RESTRICTIONS: + ${body_2(`single command cannot have multiple --app , --prog and --port conditions to kill apps with different appNames, + programNames and portNumbers in one shot.`)} + + `; + + console.log(usageMessage) +} + +export function getRunningDirs(){ + const jamFolder = getJamFolder() + const appToPort = new Map() + let activePorts + try{ + activePorts = fs.readdirSync(`${jamFolder}/ports`) + } + catch(error){ + return appToPort + } + for(let port of activePorts){ + let apps; + try{ + apps = fs.readFileSync(`${jamFolder}/ports/${port}`).toString().trim().split("\n"); + } + catch(error){ + continue + } + for(let app of apps){ + if(appToPort.has(app)){ + const portList = appToPort.get(app); + portList.push(port) + appToPort.set(app,portList) + } + else{ + appToPort.set(app,[port]) + } + } + } + return appToPort; +} + +export function dirNameToAppName(dirName){ + const dir = dirName.split('_') + if(dir.length > 2){ + return (dir.filter((_,index) => index !== 0)).join("_") + } + else{ + return dir[1]; + } + +} + +export function dirNameToProgramName(dirName){ + return (dirName.split('_'))[0] + +} + +function killDataForAll(root){ + const toClean=[]; + const activeDirs = getRunningDirs(); + const appfolder = getAppFolder() + + for(let dir of activeDirs.keys()){ + for(let port of activeDirs.get(dir)){ + if(root){ + try{ + const rootIP = fs.readFileSync(`${appfolder}/${dir}/${port}/root`).toString().trim(); + if(rootIP === root){ + const info ={ + programName : dirNameToProgramName(dir)+".jxe", + appName : dirNameToAppName(dir), + portNumber : port + } + toClean.push(info) + } + } + catch(error){ + continue; + } + } + else{ + + const info ={ + programName : dirNameToProgramName(dir)+".jxe", + appName : dirNameToAppName(dir), + portNumber : port + } + toClean.push(info) + } + } + } + + return toClean +} +async function killJamRun(data){ + const appName = data.appName; + const programName = data.programName + const portNumber = data.portNumber + const dirName = ((programName.split('.'))[0]) +"_"+ appName; + const appfolder = getAppFolder() + try{ + const pid = fs.readFileSync(`${appfolder}/${dirName}/${portNumber}/shellpid`).toString().trim(); + const p = await $`ps -p ${pid} | grep jamrun | wc -l | tr -d '[:space:]'` + const exists = Number(p.stdout.toString().trim()); + if(exists){ + process.kill(pid); + return + } + } + catch(error){ + return + } +} + +async function killJFile(data){ + const appName = data.appName; + const programName = data.programName + const portNumber = data.portNumber + const dirName = ((programName.split('.'))[0]) +"_"+ appName; + const appfolder = getAppFolder() + try{ + const pid = fs.readFileSync(`${appfolder}/${dirName}/${portNumber}/processId`).toString().trim(); + const tmuxID = fs.readFileSync(`${appfolder}/${dirName}/${portNumber}/tmuxid`).toString().trim(); + spawnSync(TMUX, ['kill-session', '-t', `${tmuxID}-j`]); + const p = await $`ps -p ${pid} | grep node | wc -l | tr -d '[:space:]'` + const exists = Number(p.stdout.toString().trim()); + if(exists){ + process.kill(pid); + return; + } + } + catch(error){ + return + } +} + +async function killProcess(data){ + await killJamRun(data); + await killJFile(data); +} + + +function filter(data, filters){ + + const filteredInfo =[]; + for(let info of data){ + let isPassing = true + for(let filter of Object.keys(filters)){ + if(!(filters[filter] === info[filter])){ + isPassing = false + break; + } + } + if(isPassing){ + filteredInfo.push(info) + } + } + return filteredInfo; +} + +async function jamKill(args) +{ + let root = args.root + let jamData = killDataForAll(root) + let toKill; + if(args.all){ + toKill = jamData + + if(toKill.length != 0 && args.verb){ + console.log(`${body_sec_warning(`Warning: no filter specified `)}`) + } + } + + else{ + let Filter ={} + if(args.prog){ + Filter["programName"] = `${args.prog}.jxe` + } + if(args.app){ + Filter["appName"] = args.app + } + if(args.port){ + Filter["portNumber"] = args.port + } + + toKill = filter(jamData,Filter) + if(args.verb){ + console.log(`${body_sec(`Filter: ${args.prog ? ` programName -- ${body_2_line(`${args.prog}.jxe`)}`: ""}${args.app ? ` appName -- ${body_2_line(args.app)}`: ""}${args.port ? ` port -- ${body_2_line(args.port)}` : ""}`)}`) + + } + + } + + if(toKill.length === 0 && args.verb){ + if(args.all ){ + console.log(`${body_sec_warning(`Warning: no active local job available.`)}`) + } + else{ + console.log(`${body_sec_warning(`Warning: no active local job available${args.port ? ` on port -- ${body_2_line(args.port)}` : ""}${args.prog ? ` with programName -- ${body_2_line(`${args.prog}.jxe`)}`: ""}${args.app ? ` and with appName -- ${body_2_line(args.app)}`: ""} `)}`) + } + } + + for(let data of toKill){ + + const appName = data.appName; + const programName = data.programName + const portNumber = data.portNumber + + await killProcess(data); + if(args.verb){ + console.log(`${body_sec(`${body_2_line(appName)} executing ${body_2_line(programName)} on port ${body_2_line(portNumber)} successfully terminated.`)}`) + } + cleanByPortNumber(programName,appName,portNumber) + } + if(root){ + console.log("Jobs terminated."); + } + +} + +async function jamKillBruteForce(){ + + await $`pkill node`.nothrow().quiet(); + await $`pkill mosquitto`.nothrow().quiet(); + await $`pkill tmux`.nothrow().quiet(); + await $`ps aux | grep redis-server | grep -v grep | awk '{print $2}' | xargs kill`.nothrow().quiet(); + const jamfolder = getJamFolder(); + if(fs.existsSync(`${jamfolder}/ports`)) + fs.rmSync(`${jamfolder}/ports`, { recursive: true, force: true }) + if(fs.existsSync(`${jamfolder}/apps`)) + fs.rmSync(`${jamfolder}/apps`, { recursive: true, force: true }) + if(fs.existsSync(`${jamfolder}/mqttpid`)) + fs.rmSync(`${jamfolder}/mqttpid`, { recursive: true, force: true }) + +} +async function executeScript(client, command){ + return (await new Promise((resolve, reject) =>{ + client.exec(command, (err,stream) =>{ + + if (err) throw err; + let result = '' + stream.on("close", () => { + resolve(result) + }) + stream.on("data" , (data) =>{ + + if(data.includes("KILLING IS OVER")) + { + resolve(data.toString()) + } + + }) + }) + })) +} + +async function main() { + let args; + + try { + args = getKilltArgs(process.argv); + } catch (error) { + show_usage(); + error.message === "SHOW USAGE" ? null : console.log(error.message); + process.exit(1); + } + + const jamfolder = getJamFolder(); + const appfolder = getAppFolder(); + if (fs.existsSync(`${jamfolder}/remote`) && args.remote && !args.root) { + const remotes = fs.readdirSync(`${jamfolder}/remote`); + for (let remote of remotes) { + const [host, port] = remote.split("_"); + const config = { + host: host, + port: port, + username: "admin", + password: "admin", + }; + let client = await new Promise((resolve, reject) => { + const client = new Client(); + + client.on("ready", () => { + resolve(client); + }); + + client.on("error", (error) => { + reject(error); + }); + + client.connect(config); + }); + const pathExport = + "export PATH=$PATH:/home/admin/JAMScript/node_modules/.bin"; + const changeDir = "cd JAMScript/tools"; + let toExecute; + let filters = ``; + if (args.prog) { + filters = filters + `--prog==${args.prog} `; + } + if (args.app) { + filters = filters + `--app==${args.app} `; + } + if (args.port) { + filters = filters + `--port==${args.port} `; + } + filters = filters.trim(); + + if (args.flag == "reset") { + toExecute = `jamkill.mjs --reset --root=${currIP}`; + } else if (args.flag == "all") { + toExecute = `jamkill.mjs ${filters} --root=${currIP}`; + } else { + toExecute = `jamkill.mjs ${filters} --name=${args.name} --root=${currIP}`; + } + + const command = `${pathExport} && ${changeDir} && ${toExecute}`; + await executeScript(client, command); + } + } + if (args.reset) { + if (args.root) { + throw new Error( + "DOES NOT HAVE THE PERMISSION TO RESET A REMOTE MACHINE" + ); + } + + await jamKillBruteForce(); + } else if (!fs.existsSync(jamfolder)) { + throw new Error(".jamruns folder missing. JAMScript tools not setup?"); + } else if (!fs.existsSync(appfolder)) { + throw new Error( + ".jamruns/apps folder missing. JAMScript tools not setup?" + ); + } else { + await jamKill(args); + } + + process.exit(0); +} + +(async() => { + await main() +})() diff --git a/tools/jamkill.yml b/tools/jamkill.yml new file mode 100644 index 00000000..4f8e14ba --- /dev/null +++ b/tools/jamkill.yml @@ -0,0 +1,13 @@ +- name: Run JAMkill + hosts: servers + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMKill + shell: zx wrapper.mjs jamkill + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamlist-playbook.yml b/tools/jamlist-playbook.yml new file mode 100644 index 00000000..8846e7ec --- /dev/null +++ b/tools/jamlist-playbook.yml @@ -0,0 +1,13 @@ +- name: Run JAMList Command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMRun command and store logs + shell: zx wrapper.mjs jamlist --serverIP={{ ansible_host }} > jamlist.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamlist.mjs b/tools/jamlist.mjs new file mode 100755 index 00000000..376cd37d --- /dev/null +++ b/tools/jamlist.mjs @@ -0,0 +1,664 @@ +#!/usr/bin/env zx + +import { getJamListArgs } from "./parser.mjs"; +import { getAppFolder, getJamFolder } from "./fileDirectory.mjs"; +import { dirname, resolve } from "path"; +import { fileURLToPath } from "url"; +import { Client } from "ssh2"; +import { + header_1, + header_2, + body_1, + body_sec, + keyWord, + body_2, + body_2_bold, +} from "./chalk.mjs"; +import { chalk } from "zx"; + +const { debounce } = require("lodash"); +const chokidar = require("chokidar"); +const jamFolder = getJamFolder(); +let watcher; +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const jamcleanPath = resolve(__dirname, "jamclean.mjs"); +let NODESINFO = []; +let cachedInfo = []; +let currIP; +if (os.platform() === "win32") { + currIP = ( + await $`powershell (Get-NetIPAddress -AddressFamily IPv4).IPAddress`.catch( + () => "" + ) + ) + .toString() + .trim(); +} else if (os.platform() === "darwin") { + currIP = (await $`ipconfig getifaddr en0`.catch(() => "")) + .toString() + .trim(); +} else if (os.platform() === "linux") { + currIP = (await $`hostname -I`.catch(() => "")).toString().trim(); +} + +function show_usage() { + const usageMessage = ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamlist`)}${body_1( + ` -- a tool to display the active programs and their attributes.` + )} + + ${header_1(`SYNOPSIS`)} + + Usage: jamlist + [--help] + [--all] + [--monitor] + [--type==${body_sec(`program type`)}] + [--dataStore==${body_sec(`dataStore address`)}] + [--tmuxid==${body_sec(`tmuxid`)}] + [--port==${body_sec(`portNum`)}] + [--app==${body_sec(`appName`)}] + [--prog==${body_sec(`programName`)}] + [--remote] + + + + + ${header_1(`DESCRIPTION`)} + + ${keyWord( + "Note: By default jamlist lists all the active local programs and print it before terminating." + )} + + --- ${keyWord( + "jamlist displays the folloing attribute of the running apps:" + )} + + 1) NAME: ${body_2("program's app name.")} + 2) PROGRAM: ${body_2("program's program name.")} + 3) PORT: ${body_2("the MQTT port used by program.")} + 4) D-STORE: ${body_2("the dataStore used by the program.")} + 5) TYPE: ${body_2( + "either one of fog, device or cloud depending on the program's type." + )} + 7) TMUX-ID: ${body_2( + "the generic tmux ID used by the program (not including the tag)." + )} + 8) STATUS: ${body_2( + "running is only program status now." + )} + 9) HOST: ${body_2( + "localHost if program is running locally or IPAddress of the remote machine running the program." + )} + 10) UP-TIME: ${body_2( + "the duration of the program running in the format of hour-minute-sec." + )} + + + --- jamlist [--help] + ${body_2("use this flag to dispaly this usage msg.")} + + --- jamlist [--all] + ${body_2("use this flag to dispaly all the Active programs.")} + ${body_2_bold(`NOTE: + 1) This is same as using jamlist with no option and flags. + 2) Using --all disable all the filtering flags (the ones with "==").`)} + + --- jamlist [--monitor] + ${body_2(`monitor flag keeps the jamlist alive after priniting the list of programs. + as the program stays alive it re-paints the console with new info on any chnages.`)} + + --- jamlist [--remote] + ${body_2( + `Use this flag to include the remote active apps started by the local machine running the jamlist.` + )} + + --- jamlist [--type==fog] + ${body_2(`Use --type to list only active programs with a certain type. + The command above lists all the fog programs. + The valid values for type are:`)} + ${body_2_bold(`1) device + 2) cloud + 3) fog`)} + + --- jamlist [--dataStore==127.0.0.1:21883] + ${body_2( + `used --dataStore option to list all the active apps with the given dataStore address.` + )} + + --- jamlist [--tmuxid==tg-25165] + ${body_2( + `used ---tmuxid option to list all the active apps with the given tmuxid.` + )} + + --- jamlist [--port=3] + ${body_2( + `used --port option to list all the active apps running on the given port.` + )} + + --- jamlist [--app==XX3] + ${body_2( + `used --app option to list all the active apps with the given app name.` + )} + + --- jamlist [--prog==X] + ${body_2( + `used --prog option to list all the active apps with the given program name.` + )} + + NOTE: + --type, --dataStore, --tmuxid, --port, --app and --prog are filters and can be used together. + + `; + + console.log(usageMessage); +} + +function getUpTime(startStamp) { + const now = Date.now(); + const Diff = now - startStamp; + const hours = Math.floor(Diff / (1000 * 60 * 60)); + const minutes = Math.floor((Diff % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((Diff % (1000 * 60)) / 1000); + + let result = ""; + + if (hours !== 0) { + result = result + `${hours}h `; + } + if (minutes !== 0) { + result = result + `${minutes}min `; + } + if (seconds !== 0) { + result = result + `${seconds}sec`; + } + if (result === "") { + result = Diff + "ms"; + } + + return result; +} + +export function getRunningDirs() { + const jamFolder = getJamFolder(); + const appToPort = new Map(); + let activePorts; + try { + activePorts = fs.readdirSync(`${jamFolder}/ports`); + } catch (error) { + return appToPort; + } + for (let port of activePorts) { + let apps; + try { + apps = fs + .readFileSync(`${jamFolder}/ports/${port}`) + .toString() + .trim() + .split("\n"); + } catch (error) { + continue; + } + for (let app of apps) { + if (appToPort.has(app)) { + const portList = appToPort.get(app); + portList.push(port); + appToPort.set(app, portList); + } else { + appToPort.set(app, [port]); + } + } + } + return appToPort; +} +function getWatchList(filters) { + const watchList = []; + const appFolder = getAppFolder(); + watchList.push(`${jamFolder}/ports`); + if (filters.remote) { + watchList.push(`${jamFolder}/remote`); + } + const dirs = getRunningDirs(); + for (let dir of dirs.keys()) { + for (let port of dirs.get(dir)) { + watchList.push(`${appFolder}/${dir}/${port}/numCnodes`); + } + } + return watchList; +} + +function watch(filters) { + setInterval(async () => { + await $`zx ${jamcleanPath}`; + if (cachedInfo) { + console.clear(); + printHeader(); + printNodeInfo(cachedInfo); + } + }, 1000); + function updateWatchList(watchList) { + const newWatchList = getWatchList(filters); + for (let item of newWatchList) { + if (!watchList.includes(item)) { + watcher.add(item); + } + } + for (let item of watchList) { + if (!newWatchList.includes(item)) { + watcher.unwatch(item); + } + } + return newWatchList; + } + const updateInfo = debounce(async () => { + await sleep(500); + if ( + !filters || + filters.all === true || + Object.keys(filters).length === 0 + ) { + const info = getNodeInfo(); + if (filters.remote) { + NODESINFO = []; + await main(true); + } + + if (info.length + NODESINFO.length === 0) { + console.clear(); + console.log("There is no program running"); + cachedInfo = null; + } else { + console.clear(); + printHeader(); + printNodeInfo(info); + if (filters.remote) { + printNodeInfo(NODESINFO); + } + cachedInfo = info.concat(NODESINFO); + } + } else { + const nodeinfo = getNodeInfo(); + let keysToRemove = ["root", "remote", "help", "all"]; + let filteredObj = Object.keys(filters) + .filter((key) => !keysToRemove.includes(key)) + .reduce((acc, key) => { + acc[key] = filters[key]; + return acc; + }, {}); + const filtered = filter(nodeinfo, filteredObj); + + if (filters.remote) { + NODESINFO = []; + await main(true); + } + + if (filtered.length + NODESINFO.length === 0) { + console.clear(); + console.log("There is no such program running"); + cachedInfo = null; + } else { + console.clear(); + printHeader(); + printNodeInfo(filtered); + if (filters.remote) { + printNodeInfo(NODESINFO); + } + cachedInfo = filtered.concat(NODESINFO); + } + } + }, 500); + let watchList = getWatchList(filters); + watcher = chokidar + .watch(watchList, { persistent: true, ignoreInitial: true }) + .on("all", (event, path) => { + watchList = updateWatchList(watchList); + updateInfo(); + }); +} + +export function dirNameToAppName(dirName) { + const dir = dirName.split("_"); + if (dir.length > 2) { + return dir.filter((_, index) => index !== 0).join("_"); + } else { + return dir[1]; + } +} +export function dirNameToProgramName(dirName) { + return dirName.split("_")[0]; +} + +function getNodeInfo(root = null) { + const appToPortMap = getRunningDirs(); + const jamfolder = getJamFolder(); + const appfolder = getAppFolder(); + const nodeInfo = []; + if ( + !fs.existsSync(`${jamfolder}/ports`) || + !fs.existsSync(`${jamfolder}/apps`) + ) { + return []; + } + + for (let app of appToPortMap.keys()) { + const appName = dirNameToAppName(app); + const programName = dirNameToProgramName(app); + for (let port of appToPortMap.get(app)) { + if (root) { + if (fs.existsSync(`${appfolder}/${app}/${port}/root`)) { + const rootIP = fs + .readFileSync(`${appfolder}/${app}/${port}/root`) + .toString() + .trim(); + if (rootIP === root) { + const fileNames = { + machType: "-", + dataStore: "-", + tmuxid: "-", + parentId: "-", + numCnodes: "-", + startStamp: "-", + }; + const dirPath = `${appfolder}/${app}/${port}`; + if (!fs.existsSync(`${appfolder}/${app}/${port}`)) { + throw new Error( + "FileDirectory is corrupted. TAKE REQUIRED ACTION" + ); + } + for (let fileName of Object.keys(fileNames)) { + if (fs.existsSync(`${dirPath}/${fileName}`)) { + const data = fs + .readFileSync(`${dirPath}/${fileName}`) + .toString() + .trim(); + fileNames[fileName] = data; + } + } + fileNames["port"] = String(port); + fileNames["app"] = appName; + fileNames["prog"] = programName; + fileNames["status"] = "running"; + fileNames["host"] = currIP; + + nodeInfo.push(fileNames); + } + } + } else { + const fileNames = { + machType: "-", + dataStore: "-", + tmuxid: "-", + parentId: "-", + numCnodes: "-", + startStamp: "-", + }; + const dirPath = `${appfolder}/${app}/${port}`; + if (!fs.existsSync(`${appfolder}/${app}/${port}`)) { + throw new Error( + "FileDirectory is corrupted. TAKE REQUIRED ACTION" + ); + } + for (let fileName of Object.keys(fileNames)) { + if (fs.existsSync(`${dirPath}/${fileName}`)) { + const data = fs + .readFileSync(`${dirPath}/${fileName}`) + .toString() + .trim(); + fileNames[fileName] = data; + } + } + fileNames["port"] = String(port); + fileNames["app"] = appName; + fileNames["prog"] = programName; + fileNames["status"] = "running"; + fileNames["host"] = "localHost"; + + nodeInfo.push(fileNames); + } + } + } + + return nodeInfo; +} + +function printNodeInfo(info) { + for (let row of info) { + if (row["host"] === currIP) { + row["host"] = "localHost"; + } + + let UPTIME = getUpTime(row["startStamp"]); + const headerString = ` ${row["app"].padEnd(10)} ${row["prog"].padEnd( + 10 + )} ${("Local:" + row["port"]).padEnd(10)} ${row["dataStore"].padEnd( + 20 + )} ${row["machType"].padEnd(10)} ${row["numCnodes"].padEnd(10)} ${row[ + "tmuxid" + ].padEnd(10)} ${row["status"].padEnd(10)} ${row["host"].padEnd( + 10 + )} ${UPTIME.padEnd(10)}`; + console.log(headerString); + } +} + +function printHeader() { + const headerString = ` ${chalk.bold.italic( + "APP".padEnd(10) + )} ${chalk.bold.italic("PROGRAM".padEnd(10))} ${chalk.bold.italic( + "PORT".padEnd(10) + )} ${chalk.bold.italic("D-STORE".padEnd(20))} ${chalk.bold.italic( + "TYPE".padEnd(10) + )} ${chalk.bold.italic("C-NODES".padEnd(10))} ${chalk.bold.italic( + "TMUX-ID".padEnd(10) + )} ${chalk.bold.italic("STATUS".padEnd(10))} ${chalk.bold.italic( + "HOST".padEnd(10) + )} ${chalk.bold.italic("UP-TIME".padEnd(10))}`; + console.log(headerString); + // console.log(`${chalk.black.cyan("--------------------------------------------------------------------------------------------------------------")}`) + console.log( + `${chalk.cyan( + "=========================================================================================================================" + )}` + ); +} + +function filter(nodeinfo, filters) { + const filteredInfo = []; + for (let info of nodeinfo) { + let isPassing = true; + for (let filter of Object.keys(filters)) { + if (!(filters[filter] === info[filter])) { + isPassing = false; + break; + } + } + if (isPassing) { + filteredInfo.push(info); + } + } + return filteredInfo; +} + +function getRemoteMachines() { + const jamfolder = getJamFolder(); + if (!fs.existsSync(`${jamfolder}/remote`)) { + return []; + } + return fs.readdirSync(`${jamfolder}/remote`); +} + +async function makeConnection(config) { + return await new Promise((resolve, reject) => { + const client = new Client(); + client.on("ready", () => { + resolve(client); + }); + + client.on("error", (error) => { + reject(error); + }); + + client.connect(config); + }); +} + +async function executeScript(client, command) { + return await new Promise((resolve, reject) => { + client.exec(command, (err, stream) => { + if (err) console.log(error); + stream.on("close", () => { + resolve("closed"); + }); + stream.on("data", (data) => { + if (data.includes("NODEINFO##")) { + let JSONrow = data.toString().trim().split("##")[1]; + let row; + try { + row = JSON.parse(JSONrow); + } catch (error) { + console.log(error); + } + + NODESINFO.push(row); + } + }); + }); + }); +} + +async function main(update = null) { + NODESINFO = []; + + let args; + try { + args = getJamListArgs(process.argv); + } catch (error) { + show_usage(); + console.log(error.message); + process.exit(1); + } + const filters = args.filters; + const monitor = args.monitor; + + const jamfolder = getJamFolder(); + if (filters.remote || update) { + const map = getRemoteMachines(); + + for (let machines of map) { + const [host, port] = machines.split("_"); + const config = { + host: host, + port: 22, + username: "maheswar", + password: "pass4des", + }; + const client = await makeConnection(config); + const pathExport = + "export PATH=$PATH:/home/admin/JAMScript/node_modules/.bin"; + const changeDir = "cd JAMScript/tools"; + let args = ""; + for (let filter of Object.keys(filters)) { + if (filter === "remote") { + continue; + } + if (filter === "all" || filter === "help") { + if (filters.filter) { + args = args + `--${filter} `; + } + continue; + } + args = args + `--${filter}=${filters[filter]} `; + } + args = args.trim(); + + const script = `jamlist.mjs ${args} --root=${currIP}`; + await executeScript( + client, + `${pathExport} && ${changeDir} && ${script}` + ); + } + } + + if (filters.root) { + if (filters.all) { + await $`zx ${jamcleanPath}`; + + const info = getNodeInfo(filters.root); + + for (let row of info) { + const jsonRow = JSON.stringify(row); + + await sleep(50); + } + } else { + await $`zx ${jamcleanPath}`; + const nodeinfo = getNodeInfo(filters.root); + + let keysToRemove = ["root", "remote", "help", "all"]; + let filteredObj = Object.keys(filters) + .filter((key) => !keysToRemove.includes(key)) + .reduce((acc, key) => { + acc[key] = filters[key]; + return acc; + }, {}); + const filtered = filter(nodeinfo, filteredObj); + + if (filtered.length === 0) { + process.exit(0); + } + for (let row of filtered) { + const jsonRow = JSON.stringify(row); + console.log(`NODEINFO##${jsonRow}`); + await sleep(50); + } + } + } else if (!update) { + if (filters.all) { + await $`zx ${jamcleanPath}`; + const info = getNodeInfo(); + if (info.length + NODESINFO.length === 0) { + if (!monitor) { + process.exit(0); + } + } + console.clear(); + printHeader(); + printNodeInfo(info); + printNodeInfo(NODESINFO); + cachedInfo = info.concat(NODESINFO); + } else { + await $`zx ${jamcleanPath}`; + const nodeinfo = getNodeInfo(); + let keysToRemove = ["root", "remote", "help", "all"]; + let filteredObj = Object.keys(filters) + .filter((key) => !keysToRemove.includes(key)) + .reduce((acc, key) => { + acc[key] = filters[key]; + return acc; + }, {}); + + const filtered = filter(nodeinfo, filteredObj); + if (filtered.length + NODESINFO.length === 0) { + console.log("there is No such program running"); + if (!monitor) { + process.exit(0); + } + } + console.clear(); + printHeader(); + printNodeInfo(filtered); + printNodeInfo(NODESINFO); + cachedInfo = filtered.concat(NODESINFO); + } + if (monitor) { + watch(filters); + } + } +} + +(async () => { + await main(); +})(); diff --git a/tools/jamlist.yml b/tools/jamlist.yml new file mode 100644 index 00000000..de91e5b6 --- /dev/null +++ b/tools/jamlist.yml @@ -0,0 +1,13 @@ +- name: Run JAMList + hosts: servers + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMList command + shell: zx wrapper.mjs jamlist > jamlist.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamlog.mjs b/tools/jamlog.mjs new file mode 100755 index 00000000..fb9fa7d3 --- /dev/null +++ b/tools/jamlog.mjs @@ -0,0 +1,363 @@ +#!/usr/bin/env zx + +import { getAppFolder, getJamFolder } from "./fileDirectory.mjs"; +import { getLogArgs } from "./parser.mjs"; +const readline = require('readline'); +import { Client } from 'ssh2'; +import { header_1,header_2 , body_1, body_sec, keyWord, body_2,body_2_bold } from "./chalk.mjs"; + + +function show_usage(){ + const usageMessage = + ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamlog`)}${body_1(` -- a tool to display archived or live, J node and C node log files.`)} + + ${header_1(`SYNOPSIS`)} + + Usage: jamlog + --program = ${body_sec(`programName`)} && --app = ${body_sec(`appName`)} && --port = ${body_sec(`portNum`)} + [--help] + [--all] + [--remote = ${body_sec(`IPAddress`)}] + [--tail = ${body_sec('num')}] + [--c] + [--j] + + + + ${header_1(`DESCRIPTION`)} + + --- ${keyWord('jamlog')} can't be used without arguments. + + --- jamlog --help + ${body_2(`Usethis flag to display the usage msg.`)} + + --- jamlog --program=jt2 --app=xxx2 --port=1883 + ${body_2(`Use this three options to get the specific log file of an app which runs a program on a certain port. + The command above prints the log for xxx2 app running a jt2 program on port 1883.`)} + ${body_2_bold(`NOTE: + 1) All three of these options are mandatory for jamlog to work. + 2) If there is a program currently running with the above info jamlog will print the running program log, + otherwise jamlog will print the archive log on that port if exists.`)} + + + --- jamlog --program=jt2 --app=xxx2 --port=1883 [--remote=] + ${body_2(`Use --remote option to print the log of the running program on a remote machine with a given IPaddress.`)} + + --- jamlog --program=jt2 --app=xxx2 --port=1883 [--c] [--j] + ${body_2(`Use either or both --c flag and --j flag to get either or both C node and J node log files for the given program.`)} + ${body_2_bold(`NOTE: By default jamlog will print both C node and J node log files.`)} + + --- jamlog --program=jt2 --app=xxx2 --port=1883 [--tail=4] + ${body_2(`Use the tail flag to only get last few lines of log files. + the command above displays the last 4 lines of log files. + Useful for finding the error and avoid over populating the console `)} + + `; + console.log(usageMessage) +} + + + +function printlogArchived(path,tail){ + const appfolder = getAppFolder() + if(tail) { + const fileName = path.split("/").pop(); + + if (fileName.includes("j")) { + const string = (fs.readFileSync(`${path}`).toString().trim()) + const lines = string.split('\n'); + const lastNLines = lines.slice(-Number(tail)); + console.log(`---\nworker number J file \n---`) + console.log(lastNLines.join('\n')) + + } else { + return new Promise((resolve) =>{ + console.log(`\nLast ${tail} lines of C-NODES`); + const myLineC = readline.createInterface({ + input: fs.createReadStream(path), + }); + + const linesC = []; + let header; + let cNode = []; + myLineC.on('line', (line) => { + if (line.includes('worker number')) { + if (cNode.length !== 0) { + // linesC.push("---") + linesC.push(header) + linesC.push("---") + linesC.push(cNode.join("\n")); + + } + header = line + + + } + + cNode.push(line); + if (cNode.length > tail) { + cNode.shift(); + } + + }); + + myLineC.on('close', () => { + + // linesC.push("---") + linesC.push(header) + linesC.push("---") + linesC.push(cNode.join("\n")); + + + console.log(linesC.join('\n')); + resolve() + }); + }) + + } + + } + + else{ + const data = fs.readFileSync(path, 'utf8'); + console.log(data); + } +} + + +async function makeConnection(config){ + return await new Promise((resolve, reject) => { + const client = new Client(); + client.on('ready', () => { + resolve(client); + }); + + client.on('error', (error) => { + reject(error); + }); + + client.connect(config); + }); +} + +async function executeScript(client, command){ + return (await new Promise((resolve, reject) =>{ + client.exec(command, (err,stream) =>{ + if (err) console.log(error); + stream.on("close", () => { + resolve("closed") + }) + stream.on("data" , (data) =>{ + console.log(data.toString()) + }) + }) + })) +} + +async function main(){ + let arg; + try{ + arg = getLogArgs(process.argv) + } + catch(error){ + show_usage() + console.log(error.message); + process.exit(1); + + + + } + const flag = arg.flag; + const port =Number(arg.file.split("/")[ arg.file.split("/").length-1]); + const logFiles =arg.file.split("/")[0]+"/log"; + const tail = arg.tail + const appFolder = getAppFolder() + const jamfolder = getJamFolder() + const path = `${appFolder}/${logFiles}/${port}` + if(arg.remote){ + if(!fs.existsSync(`${jamfolder}/remote/localhost_${arg.remote}`)){ + console.log("there is no such remote machine available for this host") + } + + const config = { + host: "localhost", + port: arg.remote, + username: 'admin', + password: 'admin' + }; + const client = await makeConnection(config); + const pathExport ="export PATH=$PATH:/home/admin/JAMScript/node_modules/.bin" + const changeDir= "cd JAMScript/tools" + let args = ''; + //return {file : file , flag : flag, tail : options.tail, remote: options.remote} + for(let myArg of Object.keys(arg)){ + if(myArg === "file"){ + const file = arg[myArg]; + const port = file.split("/")[1]; + const app = (file.split("/")[0]).split("_")[1]; + const program = (file.split("/")[0]).split("_")[0]; + args = args + `--app=${app} --program=${program} --port=${port} ` + } + if(myArg === "flag"){ + if(arg.flag === "all"){ + args = args + `--j --c ` + } + else{ + args = args + `--${arg.flag} ` + } + + } + if(myArg === "tail"){ + args = args + `--tail=${arg.tail} ` + } + } + const finalArg = args.trim() + + const command = `${pathExport} && ${changeDir} && jamlog.mjs ${finalArg}` + + await makeConnection(config) + await executeScript(client, command) + process.exit(0) + + + } + + if(fs.existsSync(`${appFolder}/${arg.file}`)){ + if(flag === "all"){ + if(!fs.existsSync(`${appFolder}/${arg.file}/log.j`)){ + console.log("we do not have the log file for j files") + } + const string = (fs.readFileSync(`${appFolder}/${arg.file}/log.j`).toString().trim()) + if(tail){ + const lines = string.split('\n'); + const lastNLines = lines.slice(-Number(tail)); + console.log(`---\nworker number J file \n---`) + console.log(lastNLines.join('\n')) + } + else{ + + + console.log(`---\nworker number J file \n---`) + console.log(string) + } + + const cFiles = fs.readdirSync(`${appFolder}/${arg.file}`).filter((entry) => (entry.includes("log") && !entry.includes(".j"))); + if(cFiles.length === 0 ){ + console.log("we do not have the log files for c files") + } + else{ + for(let cFile of cFiles ){ + const string = fs.readFileSync(`${appFolder}/${arg.file}/${cFile}`).toString().trim() + if(tail){ + const lines = string.split('\n'); + const lastNLines = lines.slice(-Number(tail)); + console.log(`---\nworker number ${cFile.split(".")[1]} \n---`) + + console.log(lastNLines.join('\n')) + } + else{ + + console.log(`---\nworker number ${cFile.split(".")[1]} \n---`) + console.log(string) + } + } + } + + } + else if(flag === "j"){ + + if(!fs.existsSync(`${appFolder}/${arg.file}/log.j`)){ + console.log("we do not have the log file for j files") + } + const string = (fs.readFileSync(`${appFolder}/${arg.file}/log.j`).toString().trim()) + if(tail){ + const lines = string.split('\n'); + const lastNLines = lines.slice(-Number(tail)); + console.log(`---\nworker number J file \n---`) + console.log(lastNLines.join('\n')) + } + else{ + + + console.log(`---\nworker number J file \n---`) + console.log(string) + } + + } + else{ + const cFiles = fs.readdirSync(`${appFolder}/${arg.file}`).filter((entry) => (entry.includes("log") && !entry.includes(".j"))); + if(cFiles.length === 0 ){ + console.log("we do not have the log files for c files") + } + else{ + for(let cFile of cFiles ){ + const string = fs.readFileSync(`${appFolder}/${arg.file}/${cFile}`).toString().trim() + if(tail){ + const lines = string.split('\n'); + const lastNLines = lines.slice(-Number(tail)); + console.log(`---\nworker number ${cFile.split(".")[1]} \n---`) + + console.log(lastNLines.join('\n')) + } + else{ + + console.log(`---\nworker number ${cFile.split(".")[1]} \n---`) + console.log(string) + } + } + } + + } + } + else{ + if(port){ + if(!fs.existsSync(path)){ + console.log(`THERE IS NO LOG ON ${port} for ${logFiles.split("/")[0]}`) + } + + if(flag === "all"){ + if(!fs.existsSync(`${path}/log.j`)){ + console.log(`There is no log for C files on port ${port} for ${logFiles.split("/")[0]}`) + } + else{ + + await printlogArchived(`${path}/log.j`,tail) + + } + if(!fs.existsSync(`${path}/log.c`)){ + console.log(`There is no log for C files on port ${port} for ${logFiles.split("/")[0]}`) + } + else{ + await printlogArchived(`${path}/log.c`,tail) + } + } + else if(flag === "j"){ + if(!fs.existsSync(`${path}/log.j`)){ + console.log(`There is no log for C files on port ${port} for ${logFiles.split("/")[0]}`) + } + else{ + await printlogArchived(`${path}/log.j`,tail) + } + } + else if(flag === "c"){ + if(!fs.existsSync(`${path}/log.c`)){ + console.log(`There is no log for C files on port ${port} for ${logFiles.split("/")[0]}`) + } + else{ + await printlogArchived(`${path}/log.c`,tail) + } + } + } + } + + +} + + +(async () =>{ + await main() + +})() \ No newline at end of file diff --git a/tools/jamlog.yml b/tools/jamlog.yml new file mode 100644 index 00000000..970886cc --- /dev/null +++ b/tools/jamlog.yml @@ -0,0 +1,13 @@ +- name: Run JAMLog Command + hosts: '{{ server }}' + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMLog and store logs + shell: zx wrapper.mjs jamlog --program=jt1.jxe --app=DEMO --port=1883 > jamlog.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamrun-playbook.yml b/tools/jamrun-playbook.yml new file mode 100644 index 00000000..a31c2d65 --- /dev/null +++ b/tools/jamrun-playbook.yml @@ -0,0 +1,13 @@ +- name: Run JAMRun Command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMRun command and store logs + shell: zx wrapper.mjs jamrun "{{ file }}" "{{ app }}" --bg --serverIP={{ ansible_host }} > jamrun.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools \ No newline at end of file diff --git a/tools/jamrun.mjs b/tools/jamrun.mjs new file mode 100755 index 00000000..c4592087 --- /dev/null +++ b/tools/jamrun.mjs @@ -0,0 +1,846 @@ +#!/usr/bin/env zx + +import { jamrunParsArg, getCargs, getJargs, getRemoteArgs } from "./parser.mjs"; +import { fileURLToPath } from "url"; +import { cleanByPortNumber } from "./cleanUp.mjs"; +import { dirname, resolve } from "path"; +import { + fileDirectorySetUp, + isValidExecutable, + fileDirectoryMqtt, + getPaths, + getappid, + getFolder, + cleanExecutables, + getJamFolder, + getFileNoext, +} from "./fileDirectory.mjs"; +const { spawn } = require("child_process"); +import { Client } from "ssh2"; +import { + body_1, + header_1, + header_2, + body_sec, + keyWord, + bodyBold, + body_2, + body_2_bold, + body_sec_warning, +} from "./chalk.mjs"; + +let app, + tmux, + num, + edge, + data, + local_registry, + bg, + NOVERBOSE, + log, + old, + local, + valgrind, + long, + lat, + Type, + tags, + file, + port, + remote, + root; +let removablePort; + +process.on("SIGINT", () => { + if (removablePort) { + const fileNoext = getFileNoext(file); + cleanByPortNumber( + `${fileNoext}.jxe`, + app, + removablePort, + NOVERBOSE + ); + process.exit(); + } else { + process.exit(); + } +}); + +process.on("SIGTERM", () => { + if (removablePort) { + + const fileNoext = getFileNoext(file); + cleanByPortNumber( + `${fileNoext}.jxe`, + app, + removablePort, + NOVERBOSE + ); + process.exit(); + + } else { + process.exit(); + } +}); + +const filePath = fileURLToPath(import.meta.url); +const IDIR = path.dirname(filePath); +const REDISFUNCS = fs.realpathSync(`${IDIR}/../deps/lua/jredlib.lua`); +const SHELLPID = process.pid; + +const [MOSQUITTO, MOSQUITTO_PUB, TMUX] = await Promise.all( + ["mosquitto", "mosquitto_pub", "tmux"].map(async (entry) => { + try { + const p = await $`which ${entry}`; + return p.stdout.trim(); + } catch (error) { + switch (entry) { + case "tmux": + throw new Error("tmux not installed. Quitting."); + case "mosquitto_pub": + throw new Error( + "mosquitto_pub (MQTT tools) not installed. Quitting." + ); + case "mosquitto": + throw new Error( + "mosquitto (MQTT broker) not installed. Quitting." + ); + } + } + }) +); + +async function executeScript(client, command) { + console.log("Execute Script cmd ", command); + command = "echo $PATH"; + + return await new Promise((resolve, reject) => { + client.exec(command, (err, stream) => { + if (err) { + console.log("Rejected...."); + reject(err); + } + let result; + stream.on("close", () => { + console.log("Closing..."); + resolve(result); + }); + stream.on("data", async (data) => { + console.log("hi --------------- ", data.toString()); + if (data.includes("MY PORT IS:")) { + result = data.toString().trim().split(":")[1]; + } + if (data.includes("EXIT BG")) { + resolve(result); + } + }); + }); + }); +} +//tested.working +function show_usage() { + const usageMessage = ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamrun`)}${body_1( + ` -- a tool to run JXE files with a given name` + )} + + ${header_1(`SYNOPSIS`)} + + Usage: jamrun file.jxe + + --app = ${body_sec(`app_name`)} + [--help] + [--fog | --cloud | --device] + [--num = ${body_sec(`num_c_devs`)}] + [--data = ${body_sec(`data-url`)}] + [--tags = ${body_sec(`quoted_list_of_tags`)}] + [--bg] + [--old] + [--log] + [--verb] + [--loc = ${body_sec(`long,lat`)}] + [--edge= ${body_sec(`num_edge_connections`)}] + [--valgrind] + [--local] + [--remote = ${body_sec(`IPAddress`)}] + + ${header_1(`DESCRIPTION`)} + + --- ${keyWord( + "jamrun" + )} Runs J node and C nodes, one each, of a device with ${keyWord( + "program.jxe" + )} + under a app name X, use the ${keyWord("--app")}=${keyWord( + `X` + )} option. ${bodyBold(`It is mandatory to set the app name.`)}. + + --- jamrun --help + ${body_2("--help : use this flag to display this usage message.")} + + --- jamrun program.jxe --app=X [ --fog || --device || --cloud ] + ${body_2_bold(`Among the flags above only one of them can be used`)} + ${body_2_bold( + `If none of the flags are set the program will run as device by default` + )} + ${body_2("--fog : runs a fog node (only J node) with program.jxe.")} + ${body_2("--cloud : runs a cloud node (only J node). ")} + ${body_2("--device : runs a device node (J node and C node).")} + + --- jamrun program.jxe --app=X [ --data=127.0.0.1:7000 ] + ${body_2_bold(`By default, jamrun uses a Redis server running at 127.0.0.1:(20000+porttaken) as the + data store. To use a different Redis server use the --data option.`)} + ${body_2(`--data: Runs program.jxe and connects it to an already running Redis server at + port 7000 of the local host. Redis server can run outside the + local host (Redis needs to the configured to accept outside + connections).`)} + + --- jamrun program.jxe --app=X [ --num=4 ] + ${body_2_bold(`By default, jamrun runs one c node.`)} + ${body_2(`--num: use this option to start more than one C node at a device. + the command abouve starts the program with 4 C nodes`)} + + --- jamrun program.jxe --app=X [ --tag="param1, param2" ] + ${body_2_bold(`By default, no tag is assigned.`)} + ${body_2(`--tag: use this option to provide a set of tags to the program.`)} + + --- jamrun program.jxe --app=X [ --bg ] + ${body_2_bold(`By default, the program is running on the foreground.`)} + ${body_2(`--bg: use this flag to run a command in the background. the --bg is mandatory for the cases + that program is running on a remote machine.`)} + + --- jamrun program.jxe --app=X [ --old ] + ${body_2_bold( + `By default, the program is using the latest version in .jamruns folder.` + )} + ${body_2(`--old: use this flag to run the previous version in .jamruns folder. + You can edit that version and rerun a custom version of a file.`)} + + --- jamrun program.jxe --app=X [ --log ] + ${body_2_bold(`By default, the C node output is never stored and J node output stored only when + the program is running in the background.`)} + ${body_2(`--log: use this flag to turn on logging, capturing the output of C file and J file and + adding them to the archive when the program stops running. + This is useful for programs where the C side is crashing at the startup. + The tmux console would not run when the program crash at startup. + So the --log option allows us to see the program error messages.`)} + + --- jamrun program.jxe --app=X [ --verb ] + ${body_2(`--verb : use this flag to turn on verbose messaging.`)} + + --- jamrun program.jxe --app=X [ --valgrind ] + ${body_2( + `--valgrind : use this flag to run the cside with valgrind for leak checking.` + )} + + --- jamrun program.jxe --app=X [ --local ] + ${body_2( + `--local : use this flag to disable multicast discovery of the J node. The C node assumes that the J node in the local loopback.` + )} + + --- jamrun program.jxe --app=X [ --remote=IPAddress ] [ --bg ] + ${body_2_bold(`the --remote and --bg flag should always be used together. + remote programs can only run on the background`)} + ${body_2( + `--remote: use this option to run the program on remote machine and in the background` + )} + + --- jamrun program.jxe --app=X [ --loc=long,lat ] + ${body_2_bold( + `By default, a random long and lat will be assigned to the running program` + )} + ${body_2( + `--loc: use this option to run the program with and specific long and lat value` + )} + + ${header_2( + `The jamrun command creates a run state in the $HOME/.jamruns folder.` + )} + `; + console.log(usageMessage); +} + +//teste.working. +async function startmqtt(port, cFile) { + const jamfolder = getJamFolder(); + try { + await $`${MOSQUITTO_PUB} -p ${port} -t "test" -m "hello"`.quiet(); + } catch (error) { + if (!NOVERBOSE) { + console.log(`${body_sec( + `MQTT is not running at ${port}... Attempting to start MQTT at ${port}` + )}`); + } + const command = MOSQUITTO; + const args = ["-c", cFile]; + const options = { + stdio: ["ignore", "ignore", "ignore"], + detached: true, + }; + const mqttProcesse = spawn(command, args, options); + if (!NOVERBOSE) { + console.log(`${body_sec( + `MQTT succesfully running on port ${port}` + )}`); + } + fs.writeFileSync(`${jamfolder}/mqttpid/${port}`, `${mqttProcesse.pid}`); + mqttProcesse.unref(); + + return; + } +} + +async function dojamout(iport, folder, jappid) { + await dojamout_p1(iport, folder); + await dojamout_p2(iport, folder, jappid); +} + +//tested.working +async function dojamout_p1(pnum, floc, group=null) { + await startmqtt(pnum, `${floc}/${pnum}/mqtt.conf`, data); + if (data) { + fs.writeFileSync(`${floc}/${pnum}/dataStore`, `${data}\n`); + } + fs.writeFileSync(`${floc}/${pnum}/class`, "process\n"); + fs.writeFileSync(`${floc}/${pnum}/shellpid`, SHELLPID.toString() + "\n"); + fs.writeFileSync(`${floc}/${pnum}/processId`, "new" + "\n"); + fs.writeFileSync(`${floc}/${pnum}/startStamp`, `${Date.now()}` + "\n"); + if(group){ + fs.writeFileSync(`${floc}/${pnum}/group`, `${group}` + "\n"); + } + + + + if (Type === "device") { + fs.writeFileSync(`${floc}/${pnum}/numCnodes`, `${num}`); + } + if (root) { + fs.writeFileSync(`${floc}/${pnum}/root`, root); + } +} + +async function dojamout_p2(iport, folder, jappid, group = null) { + if (!bg) { + await dojamout_p2_fg(iport, folder, jappid, group); + } else { + await dojamout_p2_bg(iport, folder, jappid, group); + } +} + +//tested, working +async function dojamout_p2_fg(pnum, floc, jappid, group = null) { + let argObject = { + "--app": jappid, + "--port": pnum, + "--group": group, + "--data": data, + "--tags": tags, + "--edge": edge, + "--long": long, + "--lat": lat, + "--localregistryhost": local_registry, + "--type": Type, + }; + + let jargs = getJargs(argObject); + if (!NOVERBOSE) { + console.log(`${ body_sec( + `J Node arg:\n${jargs}` + )}`); + } + const command = "node"; + const args = ["jstart.js", ...jargs]; + + if (log) { + + const options = { + cwd: floc, + stdio: ["pipe", "pipe", "pipe"], + }; + const stream = fs.createWriteStream(`${floc}/${pnum}/log.j`, { + flags: "a", + }); + const child = spawn(command, args, options); + child.stdout.on("data", (data) => { + process.stdout.write(data); + stream.write(data); + }); + + child.stderr.on("data", (data) => { + process.stderr.write(data); + stream.write(data); + }); + + child.on("exit", () => { + process.kill(process.pid, "SIGTERM"); + }); + } else { + + const options = { + cwd: floc, + stdio: "inherit", + }; + const child = spawn(command, args, options); + child.on("exit", () => { + process.kill(process.pid, "SIGTERM"); + }); + } +} + +async function dojamout_p2_bg(pnum, floc, jappid, group = null) { + let argObject = { + "--app": jappid, + "--port": pnum, + "--group": group, + "--data": data, + "--tags": tags, + "--edge": edge, + "--long": long, + "--lat": lat, + "--localregistryhost": local_registry, + "--type": Type, + }; + let jargs = getJargs(argObject); + if (!NOVERBOSE) { + console.log(`${ body_sec( + `J Node arg:\n${jargs}` + )}`); + } + await $`${TMUX} new-session -s ${tmux}-j -c ${floc} -d`; + + if (!log) { + + await $`${TMUX} send-keys -t ${tmux}-j "node jstart.js ${jargs}" C-m`; + } else { + + await $`${TMUX} send-keys -t ${tmux}-j "script -a -t 1 ${floc}/${pnum}/log.j node jstart.js ${jargs}" C-m`; + } + + if (root) { + body_sec( + `EXIT BG"` + ); + } + + process.exit(0); +} + + export async function doaout(num, port, group, datap, myf, jappid) { + let counter = 1; + if (fs.existsSync("a.out")) { + await $`cd ${myf} && chmod +x a.out`; + } + while (counter <= num) { + if (fs.existsSync("a.out")) { + const argObject = { + "-a": jappid.toString(), + "-p": port, + "-n": counter, + "-g": group, + "-t": tags, + "-o": datap, + }; + let cargs = getCargs(argObject); + if (!NOVERBOSE) { + console.log(`${body_sec( + `C node args: ${cargs}` + )}`); + } + await $`${TMUX} new-session -s ${tmux}-${counter} -c ${myf} -d`; + if (!log) { + if (valgrind) + await $`${TMUX} send-keys -t ${tmux}-${counter} ${valgrind} ./a.out ${cargs} C-m`; + else + await $`${TMUX} send-keys -t ${tmux}-${counter} ./a.out ${cargs} C-m`; + } else { + if (valgrind) + await $`${TMUX} send-keys -t ${tmux}-${counter} ${valgrind} ./a.out ${cargs} -f log C-m`; + else + await $`${TMUX} send-keys -t ${tmux}-${counter} "script -a -t 1 ${myf}/${port}/log.${counter} ./a.out" ${cargs} C-m`; + } + } + counter++; + } + +} + +async function portavailable(folder, port) { + let porttaken; + const jamFolder = getJamFolder(); + if (fs.existsSync(`${folder}/${port}`)) { + porttaken = 1; + } else { + porttaken = 0; + } + + if (porttaken === 0) { + if (!fs.existsSync(`${jamFolder}/ports/${port}`)) { + const p = + await $`netstat -lan -p tcp -f inet | grep ${port} | wc -l` + .nothrow() + .quiet(); + porttaken = Number(p.stdout.trim()) === 0 ? 0 : 1; + } else { + const runningApps = fs + .readFileSync(`${jamFolder}/ports/${port}`) + .toString() + .trim() + .split(); + const fileNoExt = getFileNoext(file); + if (runningApps.includes(`${fileNoExt}_${app}`)) { + porttaken = 1; + } else { + porttaken = 0; + } + } + } + return porttaken; +} + +function setuptmux(path, appfolder) { + fs.writeFileSync(`${path}/tmuxid`, tmux.toString() + "\n"); + fs.writeFileSync(`${appfolder}/tmuxid`, tmux.toString() + "\n"); +} + +async function startredis(port) { + try { + const p = $`redis-server --port ${port}` + .stdio("ignore", "ignore", "inherit") + .nothrow() + .quiet(); + } catch (error) {} +} + +async function waitforredis(port) { + while (true) { + try { + const p = await $`redis-cli -p ${port} -c PING`.quiet(); + if (p.stdout.trim() === "PONG") { + break; + } + } catch (error) {} + if (!NOVERBOSE) { + console.log(`${body_sec("Trying to find Redis server...")}`); + } + await sleep(1000); + } + + if (!NOVERBOSE) { + console.log(`${body_sec(`Redis running at port: ${port}`)}`); + } +} + +async function setupredis(port) { + await $`cat ${REDISFUNCS} | redis-cli -p ${port} -x FUNCTION LOAD REPLACE > /dev/null`; + await $`echo "set protected-mode no" | redis-cli -p ${port} > /dev/null`; + await $`echo 'config set save "" protected-mode no' | redis-cli -p ${port} > /dev/null`; + await $`redis-cli -p ${port} FLUSHALL`; +} + +async function resolvedata(Name) { + const [host, port] = Name.split(":"); + + await startredis(Number(port)); + await waitforredis(port); + await setupredis(port); + data = Name.split(/\s+/).join(""); +} + +async function unpack(file, folder) { + if (!old) { + if (!fs.existsSync("./MANIFEST.txt")) { + try { + await $`cd ${folder} && unzip -o ${file}`.quiet(); + } catch (error) { + throw new Error(`Problem reading file: ${file}\n${error}`); + } + } else { + let forceRedo = false; + try { + isValidExecutable(); + } catch (error) { + forceRedo = true; + } + if (!forceRedo) { + const p1 = + await $`cd ${folder} && zipgrep CREATE ${file} | awk 'NR==1{split($0,a, " "); print a[3]}'`; + const p2 = + await $`cd ${folder} && grep CREATE MANIFEST.txt | awk '{split($0,a, " "); print a[3]}'`; + const ntime = Number(p1.stdout.toString().trim()); + const ontime = Number(p2.stdout.toString().trim()); + if (ntime > ontime) { + try { + if (!NOVERBOSE) + console.log(`${body_sec_warning(`warning: outdated, unzippping again`)}`); + await $`cd ${folder} && unzip -oq ${file}`.quiet(); + } catch (error) { + throw new Error( + `Problem reading file: ${file}\n${error}` + ); + } + } + } else { + if (!NOVERBOSE) + console.log( + "The corrupted unziped files. files will be unziped again based on the existing MANIFEST.txt" + ); + await cleanExecutables(); + await $`cd ${folder} && unzip -oq ${file}`.quiet(); + } + } + } else { + if (!NOVERBOSE) { + console.log(`${body_sec_warning("WARNING: Unziped files might be outdated")}`); + } + isValidExecutable(); + } +} + +async function getjdata(folder) { + const p = + await $`cd ${folder} && grep JDATA MANIFEST.txt | awk '{split($0,a, " "); print a[3]}'` + .nothrow() + .quiet(); + return p.stdout.trim(); +} + +async function runNoneDevice(iport) { + const [jamfolder, appfolder, folder] = getPaths(file, app); + fileDirectoryMqtt(folder, iport, jamfolder, app); + const jappid = getappid(jamfolder, `${folder}/${iport}`, app, appfolder); + await dojamout(iport, folder, jappid); +} + +async function runDevice(iport, dport, group) { + const [jamfolder, appfolder, folder] = getPaths(file, app); + fileDirectoryMqtt(folder, iport, jamfolder, app); + const jappid = getappid(jamfolder, `${folder}/${iport}`, app, appfolder); + await dojamout_p1(iport, folder,group); + setuptmux(`${folder}/${iport}`, appfolder); + await doaout(num, iport, group, dport, folder, jappid); + await dojamout_p2(iport, folder, jappid, group); +} + +async function main() { + let iport; + let dport; + let group; + try { + ({ + app, + tmux, + num, + edge, + data, + local_registry, + bg, + NOVERBOSE, + log, + old, + local, + valgrind, + long, + lat, + Type, + tags, + port, + file, + remote, + root, + } = jamrunParsArg(process.argv)); + } catch (error) { + show_usage(); + error.message === "SHOW USAGE" ? null : console.log(error.message); + process.exit(1); + } + let folder; + let ifile; + let jdata; + let client; + if(!NOVERBOSE){ + if(remote) + console.log(`${body_sec(`remote job on: ${remote}`)}`) + else{ + console.log(`${body_sec(`local job`)}`) + } + + } + if (remote) { + const config = { + host: remote, + port: 22, + username: "maheswar", + password: "pass4des", + }; + + client = await new Promise((resolve, reject) => { + const client = new Client(); + + client.on("ready", () => { + resolve(client); + }); + + client.on("error", (error) => { + reject(error); + }); + if(!NOVERBOSE){ + console.log("Initiating connection to ....", config); + } + client.connect(config); + }); + const remoteArgs = getRemoteArgs(jamrunParsArg(process.argv)); + const changeDir = "cd JAMScript/tools"; + let currIP; + if (os.platform() === "win32") { + currIP = ( + await $`powershell (Get-NetIPAddress -AddressFamily IPv4).IPAddress`.catch( + () => "" + ) + ) + .toString() + .trim(); + } else if (os.platform() === "darwin") { + currIP = (await $`ipconfig getifaddr en0`.catch(() => "")) + .toString() + .trim(); + } else if (os.platform() === "linux") { + currIP = (await $`hostname -I`.catch(() => "")).toString().trim(); + } + const myPort = await executeScript( + client, + `${changeDir} && jamrun.mjs ${remoteArgs} --root=${currIP}` + ); + if(!NOVERBOSE){ + console.log("IP ", currIP, " port ", myPort); + } + const jamfolder = getJamFolder(); + const fileNoext = getFileNoext(file); + if (!fs.existsSync(`${jamfolder}/remote`)) { + fs.mkdirSync(`${jamfolder}/remote`); + } + if ( + !fs.existsSync( + `${jamfolder}/remote/${config.host}_${config.port}` + ) + ) { + fs.mkdirSync( + `${jamfolder}/remote/${config.host}_${config.port}` + ); + } + if ( + fs.existsSync( + `${jamfolder}/remote/${config.host}_${config.port}/${myPort}` + ) + ) { + const remoteApps = fs + .readFileSync( + `${jamfolder}/remote/${config.host}_${config.port}/${myPort}` + ) + .toString() + .trim() + .split("\n"); + if (!remoteApps.includes(`${fileNoext}_${app}`)) { + fs.appendFileSync( + `${jamfolder}/remote/${config.host}_${config.port}/${myPort}`, + `${fileNoext}_${app}\n` + ); + } + } else { + fs.writeFileSync( + `${jamfolder}/remote/${config.host}_${config.port}/${myPort}`, + `${fileNoext}_${app}\n` + ); + } + process.exit(0); + } + + fileDirectorySetUp(file, app); + folder = getFolder(file, app); + ifile = path.resolve(file); + process.chdir(folder); + await unpack(ifile, folder); + isValidExecutable(); + if(!NOVERBOSE){ + console.log(`${body_sec("JXE FILE SUCCESSFULLY UNZIPED")}`) + } + jdata = await getjdata(folder); + + let isDevice; + switch (Type) { + case "cloud": + iport = 9883; + isDevice = false; + + while (true) { + const porttaken = Number( + await portavailable(folder, iport) + ); + if (porttaken !== 1) { + break; + } + iport++; + } + removablePort = iport; + break; + + case "fog": + iport = 5883; + isDevice = false; + while (true) { + const porttaken = Number( + await portavailable(folder, iport) + ); + if (porttaken !== 1) { + break; + } + iport++; + } + removablePort = iport; + + break; + + case "device": + + iport = 1883; + isDevice = true; + while (true) { + const porttaken = Number( + await portavailable(folder, iport) + ); + if (porttaken !== 1) { + break; + } + iport++; + } + removablePort = iport; + + if (!local) { + group = iport - 1882; + } else group = 0; + + } + + if (jdata.toLowerCase() === "true") { + dport = iport + 20000; + + await resolvedata(`127.0.0.1:${dport}`); + } + + if (!fs.existsSync(`${folder}/${iport}`, { recursive: true })) { + fs.mkdirSync(`${folder}/${iport}`); + } + if (isDevice) await runDevice(iport, dport, group); + else await runNoneDevice(iport); + if(bg){ + process.exit(0) + } + +} + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const jamcleanPath = resolve(__dirname, "jamclean.mjs"); +await $`zx ${jamcleanPath}`; +await main(); diff --git a/tools/jamrun.yml b/tools/jamrun.yml new file mode 100644 index 00000000..74c6d2e5 --- /dev/null +++ b/tools/jamrun.yml @@ -0,0 +1,24 @@ +- name: Start JAMScript Server and Run JAMRun Command + hosts: servers + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Start the server (Express API) in the background + shell: nohup node app-docker.js > server.log 2>&1 & + args: + chdir: /home/jamtools/JAMScript/tools + async: 10 + poll: 0 + + - name: Wait for the server to initialize + pause: + seconds: 5 + + - name: Run JAMRun command and store logs + shell: zx wrapper.mjs jamrun jt1.jxe --app=DEMO --bg > jamrun.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamterm-playbook.yml b/tools/jamterm-playbook.yml new file mode 100644 index 00000000..c99fd462 --- /dev/null +++ b/tools/jamterm-playbook.yml @@ -0,0 +1,16 @@ +- name: Run JamTerm command + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMTerm with or without tmux param, and log output + shell: > + { + {{ 'zx wrapper.mjs jamterm ' ~ tmux if tmux is defined else 'zx wrapper.mjs jamterm' }} + } > jamterm.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamterm.mjs b/tools/jamterm.mjs new file mode 100755 index 00000000..913e499a --- /dev/null +++ b/tools/jamterm.mjs @@ -0,0 +1,369 @@ +#!/usr/bin/env zx + +import { getAppFolder, getJamFolder } from "./fileDirectory.mjs"; +import { Client } from 'ssh2'; +import { getTermArgs } from "./parser.mjs"; +import { header_1,header_2 , body_1, body_sec, keyWord, body_2,body_2_bold } from "./chalk.mjs"; +const { spawnSync } = require('child_process'); +const MAIN_SESH_NAME = "main" +const p = spawnSync('which', ['tmux']); +const MYTMUX = p.stdout.toString().trim() + +function show_usage(){ + const usageMessage = + ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamterm`)}${body_1(` -- a tool to display multiple C node outputs live`)} + + ${header_1(`SYNOPSIS`)} + + Usage: jamterm + [--help] + [--all] + [--remote=${body_sec(`IPAddress`)}] //NOT IMPEMENTED YET + [--app==${body_sec(`appName`)}] + [--prog==${body_sec(`programName`)}] + [--port==${body_sec(`portNum`)}] + [--pane]=${body_sec(`maxNumPane`)}] + + + ${header_1(`DESCRIPTION`)} + + --- ${keyWord('jamterm')} by default displays all the running C node and J nodes outputs in the different panes. + + + ${keyWord('restrictions')}: + + ${body_2(`2) various factors like the size of screen, terminal and resolution effects the number of + possible tmuxes to display.Maybe try a bigger screen `)} + + --- jamterm [--help] + ${body_2(`Use this flag to display this usage msg.`)} + + --- jamterm [--all] + ${body_2(`Use this flag to display all running C nodes.`)} + ${body_2_bold(`NOTE: + 2) If --all used with --all flag --app, --prog, --port, they will be disabled.`)} + + --- jamterm [--remote] + ${body_2(`NOT IMPLEMENTED YET`)} + + --- jamterm [--app==X] + ${body_2(`Use this flag to display C nodes of programs with a specific appName.`)} + + --- jamterm [--prog==X] + ${body_2(`Use this flag to display C nodes of programs with a specific programName.`)} + + --- jamterm [--port=3] + ${body_2(`Use this flag to display C nodes of programs running on a certain port.`)} + + --- jamterm [--pane=3] + + + NOTE: + ${body_2(`1) --app & --prog & --port can be used all together or two by two to which programs to display. `)} + ${body_2(`2) To set --app , --prog and --port options two equal signs has to be used.`)} + + + RESTRICTIONS: + ${body_2(`single command cannot have multiple --app , --prog and --port conditions to kill apps with different appNames, + programNames and portNumbers in one shot.`)} + + `; + + console.log(usageMessage) +} + +function getRunningDirs(){ + const jamFolder = getJamFolder() + const appToPort = new Map() + let activePorts + try{ + activePorts = fs.readdirSync(`${jamFolder}/ports`) + } + catch(error){ + return appToPort + } + for(let port of activePorts){ + let apps; + try{ + apps = fs.readFileSync(`${jamFolder}/ports/${port}`).toString().trim().split("\n"); + } + catch(error){ + continue + } + for(let app of apps){ + if(appToPort.has(app)){ + const portList = appToPort.get(app); + portList.push(port) + appToPort.set(app,portList) + } + else{ + appToPort.set(app,[port]) + } + } + } + return appToPort; +} +function dirNameToProgramName(dirName){ + return (dirName.split('_'))[0] +} +function dirNameToAppName(dirName){ + const dir = dirName.split('_') + if(dir.length > 2){ + return (dir.filter((_,index) => index !== 0)).join("_") + } + else{ + return dir[1]; + } + +} + +function getPrograms(root=null){ + const toGet=[]; + const activeDirs = getRunningDirs(); + const appfolder = getAppFolder() + + for(let dir of activeDirs.keys()){ + for(let port of activeDirs.get(dir)){ + if(root){ + try{ + const rootIP = fs.readFileSync(`${appfolder}/${dir}/${port}/root`).toString().trim(); + if(rootIP === root){ + const info = + { + path: `${appfolder}/${dir}/${port}`, + prog : dirNameToProgramName(dir), + app : dirNameToAppName(dir), + port : port + } + toGet.push(info) + } + } + catch(error){ + continue; + } + } + else{ + const info = + { + path: `${appfolder}/${dir}/${port}`, + prog : dirNameToProgramName(dir), + app : dirNameToAppName(dir), + port : port + + } + + toGet.push(info) + } + } + } + + return toGet +} +function filter(data, filters){ + const filteredInfo =[]; + for(let info of data){ + let isPassing = true + for(let filter of Object.keys(filters)){ + if(!(filters[filter] === info[filter])){ + isPassing = false + break; + } + } + if(isPassing){ + filteredInfo.push(info) + } + } + return filteredInfo; +} +async function getTmuxSessions(filteredData){ + const tmux_sesh = new Map() + + for(let data of filteredData){ + if(!fs.existsSync(`${data.path}/tmuxid`)){ + continue; + } + const tmuxID = fs.readFileSync(`${data.path}/tmuxid`).toString().trim() + + const p = await $`${MYTMUX} ls | grep ${tmuxID}`.nothrow().quiet() + if(p.stdout.toString() === ""){ + continue; + } + const tmuxSessions = (p.stdout.toString().trim().split("\n")).map((entry) => entry.split(":")[0]) + let counter = 1; + for(let tmuxSession of tmuxSessions){ + const tag = data.prog+"_"+data.app+"_"+data.port+"_"+(tmuxSession.includes("j") ? "J" : `C.${counter}`); + tmux_sesh.set(tag, tmuxSession) + counter++ + } + } + return tmux_sesh +} + + +async function split(number) { + + const targetSesh = `${MAIN_SESH_NAME}`; + let counter=1; + let splitDir = "-v" + let currPane=0 + let NexFlag = false + while(counter < number){ + try{ + if(NexFlag){ + currPane++; + NexFlag = false; + } + + + + await $`${MYTMUX} split-window ${splitDir} -t ${targetSesh}.${currPane}`.quiet() + + counter++; + } + catch(error){ + + + + + if(error.stderr.toString().trim() === "no space for new pane"){ + if(currPane >= counter){ + throw new Error("Screan or terminal to small for displaying the tmux sessions") + } + if(splitDir === "-v"){ + + splitDir = "-h" + } + else{ + + + splitDir = "-v" + NexFlag = true + } + + } + else{ + throw error; + } + + } + } + + +} + + + +function parsArgs(){ + let args; + + try { + args = getTermArgs(process.argv); + } catch (error) { + show_usage(); + error.message === "SHOW USAGE" ? null : console.log(error.message); + process.exit(1); + + } + return args +} +async function creatMainSesh(){ + try{ + await $`${MYTMUX} new-session -d -s ${MAIN_SESH_NAME}`.quiet(); + return; + } + catch(error){ + if((error.stderr.toString().trim()).includes("duplicate session")){ + await $`${MYTMUX} kill-session -t ${MAIN_SESH_NAME}`; + } + else{ + throw error + } + } + await $`${MYTMUX} new-session -d -s ${MAIN_SESH_NAME}`; +} + +async function setUpTmux(sessionMap, number){ + + await split(number) + await $`${MYTMUX} select-layout -t ${MAIN_SESH_NAME} tiled`; + let counter = 0 + + + + for(let tag of sessionMap.keys()){ + if(counter === number){ + break; + } + + + await $`unset TMUX;${MYTMUX} select-pane -t ${MAIN_SESH_NAME}.${counter}`; + + await $`${MYTMUX} select-pane -T ${tag}`; + counter++; + + } + + + + counter = 0; + + for(let tag of sessionMap.keys()){ + + const tmuxID = sessionMap.get(tag) + const myTag = `${tag}` + + await $`${MYTMUX} select-pane -t ${tmuxID}:0 -T ${myTag}`; + counter++; + + } + + counter = 0; + + + for(let tag of sessionMap.keys()){ + if(counter === number){ + break; + } + const tmuxID = sessionMap.get(tag) + await $`${MYTMUX} send-keys -t ${MAIN_SESH_NAME}.${counter} 'unset TMUX; ${MYTMUX} attach -t ${tmuxID}' C-m`; + counter++; + + } +} + +async function main(){ + const args = parsArgs() + const data = getPrograms() + let filters ={} + if(args.prog){ + filters["prog"] = `${args.prog}` + } + if(args.app){ + filters["app"] = args.app + } + if(args.port){ + filters["port"] = args.port + } + const filteredData= args.all ? data : filter(data,filters); + if(filteredData.length === 0){ + console.log("NO TMUX TO DISPLAY") + process.exit(0) + } + const sessionMap = await getTmuxSessions(filteredData); + if(sessionMap.size === 0 ){ + console.log("NO TMUX TO DISPLAY") + process.exit(0) + } + + const MAX_TMUX_NUM = args.pane > sessionMap.size ? sessionMap.size : args.pane; + await creatMainSesh(); + await setUpTmux(sessionMap,MAX_TMUX_NUM ); + // await $`${MYTMUX} a -t ${MAIN_SESH_NAME}`; + console.log(`Session '${MAIN_SESH_NAME}' created and running in detached mode.`); +} + +(async()=>{main()})() + diff --git a/tools/jamterm.yml b/tools/jamterm.yml new file mode 100644 index 00000000..e8082901 --- /dev/null +++ b/tools/jamterm.yml @@ -0,0 +1,13 @@ +- name: Run JAMTerm Command + hosts: '{{ server }}' + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Run JAMTerm command and store logs + shell: zx wrapper.mjs jamterm > jamterm.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/jamworker.mjs b/tools/jamworker.mjs new file mode 100644 index 00000000..42cfd88d --- /dev/null +++ b/tools/jamworker.mjs @@ -0,0 +1,351 @@ +#!/usr/bin/env zx +import { jamrunParsArg, getWorkerArgs } from "./parser.mjs"; +import { fileURLToPath } from "url"; +import { cleanByPortNumber } from "./cleanUp.mjs"; +import { dirname, resolve } from "path"; +import { getCargs } from "./parser.mjs"; + +import { + fileDirectorySetUp, + isValidExecutable, + fileDirectoryMqtt, + getPaths, + getAppFolder, + getappid, + getFolder, + cleanExecutables, + getJamFolder, + getFileNoext, +} from "./fileDirectory.mjs"; +const { spawn } = require("child_process"); +import { Client } from "ssh2"; +import { + body_1, + header_1, + header_2, + body_sec, + keyWord, + bodyBold, + body_2, + body_2_bold, + body_sec_warning, +} from "./chalk.mjs"; + + +const { spawnSync } = require('child_process'); +const p = spawnSync('which', ['tmux']); +const TMUX = p.stdout.toString().trim() + +function show_usage(){ + const usageMessage = + ` + ${header_1(`JAMTools 2.0`)} + + ${header_2(`jamWorker`)}${body_1(` -- a tool to modify workers on the fly.`)} + + ${header_1(`SYNOPSIS`)} + + Usage: jamWorker + [--help] + [--remove=${body_sec(`tmuxTagToRemove`)}] + [--add=${body_sec(`numWorkerToAdd`)}] + [--removeBatch=${body_sec(`numWorkerToRemove`)}] + [--app=${body_sec(`appName`)}] + [--prog=${body_sec(`programName`)}] + [--port=${body_sec(`portNum`)}] + [--verb] + [--log] + + ${header_1(`DESCRIPTION`)} + + --- ${keyWord('jamWorker')} needs to have at least one of --add, --remove, --removeBatch. + + --- jamWorker --add=3 --app=X --prog=jt2 --port=1883 [--verb] [--log] + ${body_2(`The command above adds three workers to the running app with the given criteria.`)} + ${body_2_bold(`NOTE: + Using --add without any of --app, --prog, --port will cause a graceful termination with no modification to workers.`)} + + --- jamWorker --remove=tg-34583-2 [--verb] + ${body_2(`The command above removes the worker running on tmux with such tmuxID if it exists.`)} + + --- jamWorker --removeBatch=4 [--verb] + ${body_2(`The command above removes the last 4 added workers. If there are fewer than 4 workers running, they will all be removed.`)} + ${body_2_bold(`NOTE: + Using --removeBatch without any of --app, --prog, --port will cause a graceful termination with no modification to workers.`)} + + `; + + console.log(usageMessage) +} + +function isFileActive(args){ + const port = args.port; + const app = args.app; + const prog = args. prog; + const appFolder = getJamFolder(); + if(fs.existsSync(`${appFolder}/ports/${port}`)){ + const activeApps = fs.readFileSync(`${appFolder}/ports/${port}`).toString().trim().split('\n') + if(activeApps.includes(`${prog}_${app}`)){ + return true; + } + else{ + return false; + } + + + } + else{ + return false + } +} + + +function isFileDirectoryCorrupted(args){ + const appFolder = getFolder(args.prog , args.app); + if(!fs.existsSync(`${appFolder}/${port}`)){ + return true + } + return false + +} + +function isDevice(args){ + const appFolder = getFolder(args.prog , args.app) + const type = fs.readFileSync(`${appFolder}/${args.port}/machType`).toString().trim() + if(type === "device"){ + return true + } + else{ + return false + } +} + +// function getTmuxIds(portNum, appName , programName){ +// const [jamfolder,appfolder,folder] = getPaths(programName,appName); +// if(fs.existsSync(`${folder}/${portNum}/tmuxid`)){ +// const tmuxID = fs.readFileSync(`${folder}/${portNum}/tmuxid`).toString().trim(); +// const p = spawnSync(TMUX, ['ls', '-F', '#S']); +// const runningTMUXS = p.stdout.toString().trim().split("\n"); +// const currTmuxids = runningTMUXS.filter((entry) => entry.includes(tmuxID)); +// return currTmuxids; + +// } +// else{ +// console.log(`${body_sec_warning(`appName: ${appName}, programName: ${programName} on port ${portNum} has no tmux`)}`) +// } +// } + +async function getRunningTmux(args){ + const app = args.app; + const prog = args.prog; + const port = args.port; + const [jamfolder, appfolder, folder] = getPaths(prog,app); + if(fs.existsSync(`${folder}/${port}/tmuxid`)){ + const tmuxID = fs.readFileSync(`${folder}/${port}/tmuxid`).toString().trim(); + const process = await $`${TMUX} ls | grep ${tmuxID}` + const activeCfiles = ((process.stdout.toString().trim().split('\n'))).map((entry) => (entry.split(":")[0])).filter((entry) => !entry.includes(`${tmuxID}-j`)) + return activeCfiles; + } + else{ + if(args.verb){ + console.log(`${body_sec_warning(`appName: ${app}, programName: ${prog} on port ${port} has no tmux tag`)}`) + } + } + +} + +function getGenericTag(args){ + const appFolder = getFolder(args.prog, args.app); + if(fs.existsSync(`${appFolder}/${args.port}/tmuxid`)){ + return fs.readFileSync(`${appFolder}/${args.port}/tmuxid`).toString().trim(); + } + else{ + if(args.verb){ + console.log(`${body_sec_warning(`appName: ${args.app}, programName: ${args.prog} on port ${args.port} has no tmux tag`)}`) + console.log(`${body_sec_warning(`script is terminating. No worker modification applied.`)}`) + + } + process.exit(0) + } +} + +function getLastTagNum(args){ + const appFolder = getFolder(args.prog, args.app); + if(fs.existsSync(`${appFolder}/${args.port}`)){ + const cfilesNum = (((fs.readdirSync(`${appFolder}/${args.port}`)).filter((entry) => entry.includes("cdevProcessId"))).map((entry) => entry.split(".")[1])) + if(cfilesNum.length === 0 ){ + return 0; + } + return Math.max(...cfilesNum); + } + else{ + if(args.verb){ + console.log(`${body_sec_warning(`no cfile is running for appName: ${args.app}, programName: ${args.prog} on port ${args.port}`)}`) + console.log(`${body_sec_warning(`script is terminating. No worker modification applied.`)}`) + } + process.exit(0) + + } +} +function getLastTag(args){ + const genericTag = getGenericTag(args) + const lastNum = getLastTagNum(args) + return {genericTag: genericTag, lastNum: lastNum } +} +async function addWorker(args){ + const [jamfolder, appfolder, folder] = getPaths(args.prog, args.app); + const {genericTag,lastNum} = getLastTag(args) + console.log(lastNum, "lst num") + console.log("this is my generic tag", genericTag) + let workerNum = lastNum+1; + const toAdd = args.add; + const jappid = getappid(jamfolder, `${folder}/${args.port}`, args.app, appfolder); + const dataStorePort = args.port + 20000 + const group = fs.readFileSync(`${folder}/${args.port}/group`).toString().trim() + + if (fs.existsSync(`${folder}/a.out`)) { + await $`cd ${folder} && chmod +x a.out`; + } + else{ + if(args.verb){ + console.log(`${body_sec_warning(`a.out does not exist for appName: ${args.app}, programName: ${args.prog} on port ${args.port}`)}`) + console.log(`${body_sec_warning(`file directory is corrupted.`)}`) + console.log(`${body_sec_warning(`script terminated with no worker adjustment`)}`) + } + process.exit(0) + } + let counter = 0 + while (counter < toAdd) { + if (fs.existsSync(`${folder}/a.out`)) { + const argObject = { + "-a": jappid.toString(), + "-p": args.port, + "-n": workerNum, + "-g": group, + "-t": genericTag, + "-o": dataStorePort, + }; + let cargs = getCargs(argObject); + if (args.verb) { + console.log(`${body_sec( + `C node args: ${cargs}` + )}`); + } + await $`${TMUX} new-session -s ${genericTag}-${workerNum} -c ${folder} -d`; + if (!args.log) { + + await $`${TMUX} send-keys -t ${genericTag}-${workerNum} ./a.out ${cargs} C-m`; + } else { + + await $`${TMUX} send-keys -t ${genericTag}-${workerNum} "script -a -t 1 ${folder}/${args.port}/log.${workerNum} ./a.out" ${cargs} C-m`; + } + workerNum++ + counter++; + if(args.verb){ + console.log(`${body_sec(`new worker was, tmux id:${genericTag}-${workerNum}`)}`) + } + } + else{ + if(args.verb){ + console.log(`${body_sec_warning(`a.out removed mid operation`)}`) + console.log(`${body_sec_warning(`file directory is corrupted.`)}`) + console.log(`${body_sec_warning(`only ${counter} worker was added`)}`) + } + process.exit(1) + } + + } +} +async function removeWorker(args){ + const p = await $`${TMUX} ls` + const exists = (((p.stdout.toString().trim().split('\n'))).map((entry) => (entry.split(":")[0])).filter((entry) => entry === args.remove)).length === 0 ? false : true + if(!exists){ + if(args.verb){ + console.log(`${body_sec_warning(`there is no worker running on TMUXID : ${args.remove}`)}`) + } + process.exit(1) + } + spawnSync(TMUX, ['kill-session', '-t', args.remove]); + if(args.verb){ + console.log(`${body_sec(`worker removed. tmuxID: ${args.remove}`)}`) + } + +} + +async function removeWorkerBatch(args){ + const workersTmux = await getRunningTmux(args) + if(workersTmux.length === 0 ){ + console.log(`${body_sec_warning(`No running worker available`)}`) + process.exit(0); + + } + if(args.verb){ + if(workersTmux.length < args.removeBatch){ + console.log(`${body_sec_warning(`cant't remove ${args.removeBatch} workers. there is only ${workersTmux.length} active worker`)}`) + console.log(`${body_sec(`all workers will be removed`)}`) + } + else{ + console.log(`${body_sec(`${args.removeBatch} workers will be removed`)}`) + + } + } + const counter = workersTmux.length < args.removeBatch ? workersTmux.length:args.removeBatch + for(let i = 0; i ${THRESHOLD_CPU}%" +echo "- Process MEM > ${THRESHOLD_MEM}MB" +echo "- System MEM > ${TOTAL_MEM_THRESHOLD}MB" +echo "Logging alerts to: $LOG_FILE" +echo "Auto-kill enabled: $AUTO_KILL" +echo "----------------------------------------------" + +while true; do + SERVER_PID=$(pgrep -f "$PROCESS_NAME") + STRESS_PID=$(pgrep -f "$STRESS_TEST_SCRIPT") + + if [[ -z "$SERVER_PID" ]]; then + echo "[$(date "+%Y-%m-%d %H:%M:%S")] $PROCESS_NAME not running." | tee -a "$LOG_FILE" + sleep $CHECK_INTERVAL + continue + fi + + MEM_USED_MB=$(free -m | awk '/Mem:/ {print $3}') + read CPU_K MEM_K <<< $(ps -p $SERVER_PID -o %cpu=,rss=) + CPU=$(printf "%.0f" "$CPU_K") + MEM_MB=$((MEM_K / 1024)) + + if [[ "$CPU" -ge "$THRESHOLD_CPU" || "$MEM_MB" -ge "$THRESHOLD_MEM" || "$MEM_USED_MB" -ge "$TOTAL_MEM_THRESHOLD" ]]; then + TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S") + echo "[$TIMESTAMP] ALERT: PID $SERVER_PID CPU=${CPU}% MEM=${MEM_MB}MB | System MEM=${MEM_USED_MB}MB" | tee -a "$LOG_FILE" + + if [[ "$AUTO_KILL" = true ]]; then + echo "[$TIMESTAMP] 🔪 Killing $PROCESS_NAME (PID $SERVER_PID)" | tee -a "$LOG_FILE" + kill -9 "$SERVER_PID" && echo "[$TIMESTAMP] $PROCESS_NAME killed." | tee -a "$LOG_FILE" + + if [[ ! -z "$STRESS_PID" ]]; then + echo "[$TIMESTAMP] 🔪 Killing stress script (PID $STRESS_PID)" | tee -a "$LOG_FILE" + kill -9 "$STRESS_PID" && echo "[$TIMESTAMP] Stress script killed." | tee -a "$LOG_FILE" + else + echo "[$TIMESTAMP] ℹ️ No stress script running." | tee -a "$LOG_FILE" + fi + else + echo "[$TIMESTAMP] AUTO_KILL is disabled — not killing processes." | tee -a "$LOG_FILE" + fi + fi + + if [[ "$MEM_USED_MB" -ge "$TOTAL_MEM_THRESHOLD" ]]; then + TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S") + echo "[$TIMESTAMP] SYSTEM ALERT: Total memory usage = ${MEM_USED_MB}MB" | tee -a "$LOG_FILE" + fi + + sleep $CHECK_INTERVAL +done diff --git a/tools/parser.mjs b/tools/parser.mjs new file mode 100644 index 00000000..872cd1d2 --- /dev/null +++ b/tools/parser.mjs @@ -0,0 +1,703 @@ +#!/usr/bin/env zx +import commandLineArgs from "command-line-args"; +import { error } from "console"; +import { type } from "os"; +import { string } from "random-js"; +import { fs } from "zx"; + +const path = require("path"); +const VALGRIND_OPTS = + "valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file=log_valgrind -s"; + +function generatelonglat() { + const a = Math.floor(Math.random() * 180); + const b = Math.floor(Math.random() * 10000); + const long = `${a}.${b}`; + const c = Math.floor(Math.random() * 90); + const d = Math.floor(Math.random() * 10000); + const lat = `${c}.${d}`; + return [long, lat]; +} +let [long, lat] = generatelonglat(); + +const jamrunOptionDefinitions = [ + { name: "help", type: Boolean, defaultValue: false }, + { name: "app", type: String, defaultValue: undefined }, + { name: "tags", type: String, defaultValue: undefined }, + { + name: "tmux", + type: String, + defaultValue: `tg-${Math.floor(Math.random() * 32768)}`, + }, + { name: "num", type: Number, defaultValue: 1 }, + { name: "loc", type: String, defaultValue: `${long},${lat}` }, + { name: "edge", type: Number, defaultValue: 1 }, + { name: "data", type: String, defaultValue: undefined }, + { name: "fog", type: Boolean, defaultValue: false }, + { name: "cloud", type: Boolean, defaultValue: false }, + { name: "device", type: Boolean, defaultValue: false }, + { name: "local_registry", type: Boolean, defaultValue: false }, + { name: "bg", type: Boolean, defaultValue: false }, + { name: "verb", type: Boolean, defaultValue: false }, + { name: "log", type: Boolean, defaultValue: false }, + { name: "old", type: Boolean, defaultValue: false }, + { name: "local", type: Boolean, defaultValue: false }, + { name: "valgrind", type: Boolean, defaultValue: false }, + { name: "port", type: Number, defaultValue: undefined }, + { name: "remote", type: String, defaultValue: undefined }, //the IP ADDRESS YOU WANT TO CONNECT TO + { name: "root", type: String, defaultValue: undefined }, //THE IP ADRRESS OF THE MACHINE making the remote call +]; + +const jamlistOptionDefinition = [ + { name: "help", type: Boolean, defaultValue: false }, + { name: "all", type: Boolean, defaultValue: false }, + { name: "monitor", type: Boolean, defaultValue: false }, + { name: "type", type: String, defaultValue: undefined }, + { name: "dataStore", type: String, defaultValue: undefined }, + { name: "tmuxid", type: String, defaultValue: undefined }, + { name: "port", type: String, defaultValue: undefined }, + { name: "app", type: String, defaultValue: undefined }, + { name: "prog", type: String, defaultValue: undefined }, + { name: "remote", type: Boolean, defaultValue: false }, //the IP ADDRESS YOU WANT TO CONNECT TO + { name: "root", type: String, defaultValue: undefined }, //THE IP ADRRESS OF THE MACHINE making the remote call +]; + +const jamkillOptionDefinition = [ + { name: "help", type: Boolean, defaultValue: false }, + { name: "all", type: Boolean, defaultValue: false }, + { name: "reset", type: Boolean, defaultValue: false }, + { name: "app", type: String, defaultValue: false }, + { name: "prog", type: String, defaultValue: false }, + { name: "port", type: String, defaultValue: false }, + { name: "verb", type: Boolean, defaultValue: false}, + { name: "remote", type: Boolean, defaultValue: false }, //the IP ADDRESS YOU WANT TO CONNECT TO + { name: "root", type: String, defaultValue: undefined }, //THE IP ADRRESS OF THE MACHINE making the remote call +]; + +const jamtermOptionDefinition = [ + { name: "help", type: Boolean, defaultValue: false }, + { name: "all", type: Boolean, defaultValue: false }, + { name: "app", type: String, defaultValue: false }, + { name: "prog", type: String, defaultValue: false }, + { name: "port", type: String, defaultValue: false }, + { name: "pane", type: Number, defaultValue: 16 }, + { name: "separate", type: Boolean, defaultValue: false }, + { name: "remote", type: Boolean, defaultValue: false }, //the IP ADDRESS YOU WANT TO CONNECT TO + { name: "root", type: String, defaultValue: undefined }, //THE IP ADRRESS OF THE MACHINE making the remote call +]; + +const jamclogOptionDefinition = [ + { name: "help", type: Boolean, defaultValue: false }, + { name: "program", type: String, defaultValue: undefined }, + { name: "app", type: String, defaultValue: undefined }, + { name: "port", type: String, defaultValue: undefined }, + { name: "j", type: Boolean, defaultValue: false }, + { name: "c", type: Boolean, defaultValue: false }, + { name: "tail", type: Number, defaultValue: undefined }, + { name: "remote", type: String, defaultValue: undefined }, +]; + +const jamBatchOptionDefinition = [ + { name: "fog", type: String, defaultValue: undefined }, + { name: "cloud", type: String, defaultValue: undefined }, + { name: "device", type: String, defaultValue: undefined }, + { name: "dFile", type: String, defaultValue: undefined }, + { name: "cFile", type: String, defaultValue: undefined }, + { name: "fFile", type: String, defaultValue: undefined }, + { name: "num", type: String, defaultValue: undefined }, + { name: "cLoc", type: String, defaultValue: undefined}, + { name: "fLoc", type: String, defaultValue: undefined}, + { name: "dLoc", type: String, defaultValue: undefined}, + { name: "dEdge", type: String, defaultValue: undefined}, + { name: "cEdge", type: String, defaultValue: undefined}, + { name: "fEdge", type: String, defaultValue: undefined}, + { name: "config", type: String, defaultValue: undefined}, + {name: "verb", type:Boolean, defaultValue: false} +]; +//no extention for the prog name ex) jt2 +const jamWorkerOptionDefinition = [ + { name: "help", type: Boolean, defaultValue: false }, + {name: "add", type: Number, defaultValue: undefined }, + {name: "removeBatch", type: Number , defaultValue: undefined}, + {name: "remove", type: String , defaultValue: undefined}, + {name: "port", type:Number , defaultValue: undefined}, + {name: "prog", type:String, defaultValue: undefined}, + {name: "app", type:String, defaultValue: undefined}, + {name: "verb", type:Boolean, defaultValur: false}, + {name:"log",type:Boolean, defaultValur: false} + +]; + +function retrieveType(device, fog, cloud) { + if (!fog && !device && !cloud) { + return "device"; + } else if ((fog ? 1 : 0) + (device ? 1 : 0) + (cloud ? 1 : 0) > 1) { + throw Error("Only one of fog, device, cloud flag can be true"); + } else { + if (fog) return "fog"; + if (device) return "device"; + if (cloud) return "cloud"; + } +} +function retrieveLongLat(loc) { + return ([long, lat] = loc.split(",")); +} + +function getJamrunArgs(args) { + let options; + try { + options = commandLineArgs(jamrunOptionDefinitions, { argv: args }); + } catch (error) {} + + return options; +} + +function checkJXEfile(arg) { + if ( + arg.length === 0 || + arg[0].toLowerCase() === "-h" || + arg[0].toLowerCase() === "--help" + ) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + } + + const file = `${arg[0]}`; + const fext = file.split(".").pop(); + + if (fext !== "jxe") { + if (!fext) + throw new Error(`${file} is not file name or missing extention`); + else { + throw new Error(`Extension on ${file} is not .jxe`); + } + } + const absolutePath = path.resolve(file); + if ( + !fs.existsSync(absolutePath) && + !arg.some((item) => item.startsWith("--remote=")) + ) { + throw new Error(`File: ${file} not found`); + } + + return file; +} +function SetJamrunVar(options) { + const Type = retrieveType(options.device, options.fog, options.cloud); + if (Type !== "device") { + options.num = undefined; + options.edge = undefined; + } + const NOVERBOSE = !options.verb; + const valgrid = options.valgrid ? VALGRIND_OPTS : false; + const [long, lat] = retrieveLongLat(options.loc); + + const toAdd = { + valgrind: valgrid, + long: long, + lat: lat, + NOVERBOSE: NOVERBOSE, + Type: Type, + }; + const skip = ["help", "fog", "cloud", "device", "loc", "verb"]; + const AssignedVar = {}; + for (let option of Object.keys(options)) { + if (skip.includes(option)) { + continue; + } + AssignedVar[option] = options[option]; + } + for (let option of Object.keys(toAdd)) { + AssignedVar[option] = toAdd[option]; + } + + if (!("tags" in AssignedVar)) { + AssignedVar["tags"] = undefined; + } + + return AssignedVar; +} + +//question one on remNote + +export function jamrunParsArg(argv) { + const arg = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamrun.mjs") + ); + + const file = checkJXEfile(arg); + + let proccessedArgs = arg.filter((_, index) => index !== 0); + const options = getJamrunArgs(proccessedArgs); + if (!options || options.help) { + const error = new Error("SHOW USAGE"); + error.type = "UsageError"; + throw error; + } + + for (let optionDefinition of jamrunOptionDefinitions) { + if ( + options[optionDefinition.name] === null && + optionDefinition.type != Boolean + ) { + throw new Error( + `--${optionDefinition.name} requires a non-empty option argument` + ); + } + } + const varsObject = SetJamrunVar(options); + varsObject["file"] = file; + if (!varsObject.app) { + throw new Error("MISSING APP NAME"); + } + + return varsObject; +} +//ASK wHAT VARIABLES ARE OPTIONAL +//TO BE TESTED +export function getCargs(argObject) { + let args = ""; + for (let key of Object.keys(argObject)) { + if (argObject[key] != undefined) { + args = args + ` ${key} ${argObject[key]}`; + } + } + + return args; +} +export function getJargs(argObject) { + const args = []; + for (let key of Object.keys(argObject)) { + if (argObject[key] != undefined) { + if (key === "--type") args.push(`--${argObject[key]}`); + else args.push(`${key}=${argObject[key]}`); + } + } + + return args; +} + +export function getJamListArgs(argv) { + const args = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamlist.mjs") + ); + let options; + try { + options = commandLineArgs(jamlistOptionDefinition, { argv: args }); + } catch (error) {} + + if (options.help || !options) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + } + if (Object.keys(options).length === 1) { + return "all"; + } + + const filters = {}; + for (let key of Object.keys(options)) { + if (key === "help" || key === "monitor") continue; + + if (key === "type") { + const deviceType = options[key]; + if ( + deviceType !== "device" && + deviceType !== "fog" && + deviceType !== "cloud" + ) { + throw new Error("wrong device type"); + } + filters["machType"] = deviceType; + } else { + + if ( + key === "prog" || + key === "app" || + key === "port" || + key === "type" || + key === "tmuxid" || + key === "dataStore" + ) { + if (options[key].includes("=")) + filters[key] = options[key] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + else throw new Error(`${key} is missing '='`); + } else { + filters[key] = options[key]; + } + } + } + + return { filters: filters, monitor: options.monitor }; +} + +export function getKilltArgs(argv) { + const args = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamkill.mjs") + ); + let options; + + try { + options = commandLineArgs(jamkillOptionDefinition, { argv: args }); + } catch (error) {} + + if (options === undefined || options.help) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + } + if (options["app"]) { + if (options["app"].includes("=")) { + let newOption = options["app"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + + options["app"] = newOption; + } else { + throw new Error("app argument missing '=' "); + } + } + if (options["prog"]) { + if (options["prog"].includes("=")) { + let newOption = options["prog"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + options["prog"] = newOption; + } else { + throw new Error("program argument missing '=' "); + } + } + if (options["port"]) { + if (options["port"].includes("=")) { + let newOption = options["port"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + options["port"] = newOption; + } else { + throw new Error("port argument missing '=' "); + } + } + return options; +} + + +export function getTermArgs(argv) { + const args = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamterm.mjs") + ); + let options; + + try { + options = commandLineArgs(jamtermOptionDefinition, { argv: args }); + } catch (error) {} + + if (options === undefined || options.help) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + } + if (options["app"]) { + if (options["app"].includes("=")) { + let newOption = options["app"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + + options["app"] = newOption; + } else { + throw new Error("app argument missing '=' "); + } + } + if (options["prog"]) { + if (options["prog"].includes("=")) { + let newOption = options["prog"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + options["prog"] = newOption; + } else { + throw new Error("program argument missing '=' "); + } + } + if (options["port"]) { + if (options["port"].includes("=")) { + let newOption = options["port"] + .split("=") + .slice(1) + .map((entry) => { + if (entry === "") { + return "="; + } else { + return entry; + } + }) + .join(""); + options["port"] = newOption; + } else { + throw new Error("port argument missing '=' "); + } + } + + return options; +} + +export function getRemoteArgs(argObject) { + const args = []; + args.push(argObject.file); + for (let arg of Object.keys(argObject)) { + if (argObject[arg] === false || argObject[arg] === undefined) { + continue; + } + if ( + arg === "long" || + arg === "lat" || + arg === "Type" || + arg === "NOVERBOSE" || + arg === "remote" || + arg == "file" + ) { + continue; + } + if (argObject[arg] === true) { + args.push(`--${arg}`); + } else { + args.push(`--${arg}=${argObject[arg]}`); + } + } + args.push(`--loc=${long},${lat}`); + if (argObject["NOVERBOSE"]) args.push(`--verb`); + args.push(`--${argObject["Type"]}`); + return args.join(" "); +} + + +export function getLogArgs(argv) { + const args = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamlog.mjs") + ); + let options; + let file; + let flag; + try { + options = commandLineArgs(jamclogOptionDefinition, { argv: args }); + } catch (error) { + + } + + if (options === undefined || options.help) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + } else if (!options.program || !options.app || !options.port) { + throw new Error("Missing programName or appName or port"); + } else if (options.port && options.app && options.program) { + file = `${options.program}_${options.app}/${options.port}`; + } else { + file = `${options.program}_${options.app}`; + } + + if ((options.j && options.c) || (!options.c && !options.j)) { + flag = "all"; + } else { + flag = options.j ? "j" : "c"; + } + return { + file: file, + flag: flag, + tail: options.tail, + remote: options.remote, + }; +} + + +function getJobs(names, files, locs, edges, type, cNums=null){ + const appNames = [] + const fileNames = [] + let Cnum = [] + let loc = [] + let edge = [] + const jobs = [] + + + for( let dev of names.split(",")){ + const Cnum = dev.split("-")[0]; + const appName = dev.split("-")[1]; + for(let num = 0 ; num + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jambatch.mjs") + ); + let options; + + try { + options = commandLineArgs(jamBatchOptionDefinition, { argv: args }); + } catch (error) {} + + if (options === undefined || options.help) { + const error = new Error("SHOW USAGE"); + error.type = "ShowUsage"; + throw error; + }; + if(options.config){ + return {"config":options.config , "verb" : options.verb} + } + let deviceJobs = []; + let fogJobs = []; + let cloudJobs = []; + if(!options.device && !options.fog && !options.cloud){ + throw new Error("TYPE IS NOT DEFINED") + } + if(options.device){ + deviceJobs = getJobs(options.device, options.dFile, options.dLoc, options.dEdge, "device" ,options.num); + } + if(options.fog){ + fogJobs = getJobs(options.fog, options.fFile,options.fLoc,options.fEdge,"fog"); + } + if(options.cloud){ + cloudJobs = getJobs(options.cloud, options.cFile,options.cLoc,options.cEdge,"cloud") + } + return ((deviceJobs.concat(fogJobs)).concat(cloudJobs)).concat([options.verb]); +} + +export function getWorkerArgs(argv){ + const args = argv.filter( + (entry) => + !entry.includes("node") && + !entry.includes("zx") && + !entry.includes("jamworker.mjs") + ); + let options; + + try { + options = commandLineArgs(jamWorkerOptionDefinition, { argv: args }); + } catch (error) {} + const rawMode = [options?.remove ? "remove" : undefined , options?.add ? "add" : undefined, options?.removeBatch ? "removeBatch" : undefined] + const mode = rawMode.filter((entry) => entry !== undefined) + if (options === undefined || options.help) { + throw new Error("SHOW USAGE"); + }; + if((!options?.app || !options?.prog || !options?.port) && mode[0] !=="remove"){ + throw new Error("appName, programName and portNumber should be defined"); + } + if(mode.length !== 1){ + throw new Error("the mode should be either one of remove, add, removeBatch"); + }; + options["mode"] = mode[0] + return options +} \ No newline at end of file diff --git a/tools/req-jamlist-test.mjs b/tools/req-jamlist-test.mjs new file mode 100644 index 00000000..b52f1eba --- /dev/null +++ b/tools/req-jamlist-test.mjs @@ -0,0 +1,61 @@ +#!/usr/bin/env zx +import fetch from 'node-fetch'; + +const TOTAL_REQUESTS = 500; +const CONCURRENCY = 20; +const endpoint = 'http://0.0.0.0:3000/jamlist'; + +const payload = { + all: "all" +}; + +let active = 0; +let completed = 0; +let failed = 0; + +const sendRequest = async (i) => { + try { + active++; + const res = await fetch(endpoint, { + method: 'POST', + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + if (!res.ok) { + console.error(`[${i}] Failed: ${res.status}`); + failed++; + } else { + console.log(`[${i}] Success`); + } + } catch (err) { + console.error(`[${i}] Failed: ${res.status}`); + failed++; + } finally { + completed++; + active--; + } +}; + +const runLoadTest = async () => { + console.time('Test Duration'); + let queue = []; + + for (let i = 0; i < TOTAL_REQUESTS; i++) { + const task = sendRequest(i); + queue.push(task); + + if (queue.length >= CONCURRENCY) { + await Promise.all(queue); + queue = []; + } + } + + // Await any remaining requests + await Promise.all(queue); + + console.timeEnd('Test Duration'); + console.log(`\nResults: ${completed} completed, ${failed} failed.`); +}; + +await runLoadTest(); \ No newline at end of file diff --git a/tools/req-jamrun-test.mjs b/tools/req-jamrun-test.mjs new file mode 100644 index 00000000..ad0f00f7 --- /dev/null +++ b/tools/req-jamrun-test.mjs @@ -0,0 +1,95 @@ +#!/usr/bin/env zx +import fetch from 'node-fetch'; +import os from 'os'; +import process from 'process'; + +const TOTAL_REQUESTS = 100; +const CONCURRENCY = 5; +const endpoint = 'http://0.0.0.0:3000/jamrun'; + +const payload = { + file: "jt1.jxe", + app_name: "DEMO", + bg: "bg" +}; + +let active = 0; +let completed = 0; +let failed = 0; +let queue = []; +const checkpoints = []; +const requestDurations = []; + +console.time('Test Duration'); + +const sendRequest = async (i) => { + const start = Date.now(); + try { + active++; + const res = await fetch(endpoint, { + method: 'POST', + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + + const duration = Date.now() - start; + requestDurations[i] = duration; + + if (!res.ok) { + console.error(`[${i}] Failed: ${res.status}`); + failed++; + } else { + console.log(`[${i}] Success`); + } + } catch (err) { + console.error(`[${i}] Error: ${err.message}`); + failed++; + } finally { + completed++; + active--; + + // Record checkpoint every 10 completed requests + if (completed % 10 === 0) { + const avgDuration = requestDurations + .slice(completed - 10, completed) + .reduce((a, b) => a + b, 0) / 10; + + const mem = process.memoryUsage(); + const cpu = os.loadavg()[0]; + + checkpoints.push({ + requests: completed, + avgDurationMs: avgDuration.toFixed(2), + memoryMB: (mem.rss / 1024 / 1024).toFixed(2), + cpuLoad: cpu.toFixed(2), + }); + } + } +}; + +const runLoadTest = async () => { + for (let i = 0; i < TOTAL_REQUESTS; i++) { + const task = sendRequest(i); + queue.push(task); + + if (queue.length >= CONCURRENCY) { + await Promise.all(queue); + queue = []; + } + } + + // Await remaining requests + await Promise.all(queue); +}; + +await runLoadTest(); +console.timeEnd('Test Duration'); + +console.log(`\nResults: ${completed} completed, ${failed} failed.`); + +// Print summary +console.log('\nCheckpoint Summary (Every 10 Requests)'); +console.log('Reqs\tAvg Time (ms)\tMemory (MB)\tCPU Load'); +checkpoints.forEach(cp => { + console.log(`${cp.requests}\t${cp.avgDurationMs}\t\t${cp.memoryMB}\t\t${cp.cpuLoad}`); +}); diff --git a/tools/run_all.sh b/tools/run_all.sh new file mode 100755 index 00000000..ba8a6ced --- /dev/null +++ b/tools/run_all.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +# Base command +COMMAND="zx jamrun.mjs jt1.jxe --bg" + +# Base app name +APP_PREFIX="DEMO" + +# Directory to execute the command (adjust this if necessary) +WORK_DIR="/root/capstone_team/JAMScript/tools" + +# Navigate to the working directory +cd "$WORK_DIR" || exit + +# Loop from DEMO1 to DEMO100 and execute the command +for i in {1..100}; do + APP_NAME="${APP_PREFIX}${i}" + echo "Running command: $COMMAND --app=$APP_NAME" + $COMMAND --app="$APP_NAME" +done + +echo "All commands executed." diff --git a/tools/server_resource_alerts.log b/tools/server_resource_alerts.log new file mode 100644 index 00000000..dcd3eead --- /dev/null +++ b/tools/server_resource_alerts.log @@ -0,0 +1,3371 @@ +[2025-03-26 19:19:55] app-docker.js not running. +[2025-03-26 19:19:57] app-docker.js not running. +[2025-03-26 19:19:59] app-docker.js not running. +[2025-03-26 19:21:40] ALERT: PID 2293772 CPU=1% MEM=50MB | System MEM=6036MB +[2025-03-26 19:21:40] 🔪 Killing app-docker.js (PID 2293772) +[2025-03-26 19:21:40] app-docker.js killed. +[2025-03-26 19:21:40] 🔪 Killing stress script (PID 2296600) +[2025-03-26 19:21:40] Stress script killed. +[2025-03-26 19:21:40] SYSTEM ALERT: Total memory usage = 6036MB +[2025-03-26 19:21:42] app-docker.js not running. +[2025-03-26 19:21:44] app-docker.js not running. +[2025-03-26 19:21:46] app-docker.js not running. +[2025-03-26 19:21:48] app-docker.js not running. +[2025-03-26 19:21:50] app-docker.js not running. +[2025-03-26 19:21:52] app-docker.js not running. +[2025-03-26 19:21:54] app-docker.js not running. +[2025-03-26 19:21:56] app-docker.js not running. +[2025-03-26 19:21:59] app-docker.js not running. +[2025-03-26 19:22:01] app-docker.js not running. +[2025-03-26 19:22:03] app-docker.js not running. +[2025-03-26 19:22:05] app-docker.js not running. +[2025-03-26 19:22:07] app-docker.js not running. +[2025-03-26 19:22:09] app-docker.js not running. +[2025-03-26 19:22:11] app-docker.js not running. +[2025-03-26 19:22:13] app-docker.js not running. +[2025-03-26 19:22:15] app-docker.js not running. +[2025-03-26 19:22:17] app-docker.js not running. +[2025-03-26 19:22:19] app-docker.js not running. +[2025-03-26 19:22:21] app-docker.js not running. +[2025-03-26 19:22:23] app-docker.js not running. +[2025-03-26 19:22:25] app-docker.js not running. +[2025-03-26 19:22:27] app-docker.js not running. +[2025-03-26 19:22:29] app-docker.js not running. +[2025-03-26 19:22:32] app-docker.js not running. +[2025-03-26 19:22:34] app-docker.js not running. +[2025-03-26 19:22:36] app-docker.js not running. +[2025-03-26 19:22:38] app-docker.js not running. +[2025-03-26 19:22:40] app-docker.js not running. +[2025-03-26 19:26:02] app-docker.js not running. +[2025-03-26 19:26:04] app-docker.js not running. +[2025-03-26 20:02:51] app-docker.js not running. +[2025-03-30 11:48:21] app-docker.js not running. +[2025-03-30 11:48:23] app-docker.js not running. +[2025-03-30 11:48:25] app-docker.js not running. +[2025-03-30 11:48:27] app-docker.js not running. +[2025-03-30 11:48:29] app-docker.js not running. +[2025-03-30 11:48:31] app-docker.js not running. +[2025-03-30 11:48:33] app-docker.js not running. +[2025-03-30 11:48:35] app-docker.js not running. +[2025-03-30 11:48:37] app-docker.js not running. +[2025-03-30 11:48:39] app-docker.js not running. +[2025-03-30 11:49:35] ALERT: PID 74290 CPU=1% MEM=42MB | System MEM=6206MB +[2025-03-30 11:49:35] 🔪 Killing app-docker.js (PID 74290) +[2025-03-30 11:49:35] app-docker.js killed. +[2025-03-30 11:49:35] ℹ️ No stress script running. +[2025-03-30 11:49:35] SYSTEM ALERT: Total memory usage = 6206MB +[2025-03-30 11:49:37] app-docker.js not running. +[2025-03-30 11:49:39] app-docker.js not running. +[2025-03-30 11:49:41] app-docker.js not running. +[2025-03-30 11:49:43] app-docker.js not running. +[2025-03-30 11:49:45] app-docker.js not running. +[2025-03-30 11:49:47] app-docker.js not running. +[2025-03-30 11:49:49] app-docker.js not running. +[2025-03-30 11:49:51] app-docker.js not running. +[2025-03-30 11:49:53] app-docker.js not running. +[2025-03-30 11:49:55] app-docker.js not running. +[2025-03-30 11:49:58] app-docker.js not running. +[2025-03-30 11:50:00] app-docker.js not running. +[2025-03-30 11:50:02] app-docker.js not running. +[2025-03-30 11:50:04] app-docker.js not running. +[2025-03-30 11:50:06] app-docker.js not running. +[2025-03-30 11:50:08] app-docker.js not running. +[2025-03-30 11:50:10] app-docker.js not running. +[2025-03-30 11:50:12] app-docker.js not running. +[2025-03-30 11:50:14] app-docker.js not running. +[2025-03-30 11:50:16] app-docker.js not running. +[2025-03-30 11:50:18] app-docker.js not running. +[2025-03-30 11:50:20] app-docker.js not running. +[2025-03-30 11:50:22] app-docker.js not running. +[2025-03-30 11:50:24] app-docker.js not running. +[2025-03-30 11:50:26] app-docker.js not running. +[2025-03-30 11:50:28] app-docker.js not running. +[2025-03-30 11:50:30] app-docker.js not running. +[2025-03-30 11:50:32] app-docker.js not running. +[2025-03-30 11:50:34] app-docker.js not running. +[2025-03-30 11:50:36] app-docker.js not running. +[2025-03-30 11:50:38] app-docker.js not running. +[2025-03-30 11:50:40] app-docker.js not running. +[2025-03-30 11:50:42] app-docker.js not running. +[2025-03-30 11:50:44] app-docker.js not running. +[2025-03-30 11:50:46] app-docker.js not running. +[2025-03-30 11:50:48] app-docker.js not running. +[2025-03-30 11:50:50] app-docker.js not running. +[2025-03-30 11:50:52] app-docker.js not running. +[2025-03-30 11:50:55] app-docker.js not running. +[2025-03-30 11:50:57] app-docker.js not running. +[2025-03-30 11:50:59] app-docker.js not running. +[2025-03-30 11:51:01] app-docker.js not running. +[2025-03-30 11:51:03] app-docker.js not running. +[2025-03-30 11:51:05] app-docker.js not running. +[2025-03-30 11:51:07] app-docker.js not running. +[2025-03-30 11:51:09] app-docker.js not running. +[2025-03-30 11:51:11] app-docker.js not running. +[2025-03-30 11:51:13] app-docker.js not running. +[2025-03-30 11:51:15] app-docker.js not running. +[2025-03-30 11:51:17] app-docker.js not running. +[2025-03-30 11:51:19] app-docker.js not running. +[2025-03-30 11:51:21] app-docker.js not running. +[2025-03-30 11:51:23] app-docker.js not running. +[2025-03-30 11:51:25] app-docker.js not running. +[2025-03-30 11:51:27] app-docker.js not running. +[2025-03-30 11:51:29] app-docker.js not running. +[2025-03-30 11:51:31] app-docker.js not running. +[2025-03-30 11:51:33] app-docker.js not running. +[2025-03-30 11:51:35] app-docker.js not running. +[2025-03-30 11:51:37] app-docker.js not running. +[2025-03-30 11:51:39] app-docker.js not running. +[2025-03-30 11:51:41] app-docker.js not running. +[2025-03-30 11:51:43] app-docker.js not running. +[2025-03-30 11:51:45] app-docker.js not running. +[2025-03-30 11:51:47] app-docker.js not running. +[2025-03-30 11:51:49] app-docker.js not running. +[2025-03-30 11:51:51] app-docker.js not running. +[2025-03-30 11:51:53] app-docker.js not running. +[2025-03-30 11:51:55] app-docker.js not running. +[2025-03-30 11:51:57] app-docker.js not running. +[2025-03-30 11:51:59] app-docker.js not running. +[2025-03-30 11:52:01] app-docker.js not running. +[2025-03-30 11:52:04] app-docker.js not running. +[2025-03-30 11:52:06] app-docker.js not running. +[2025-03-30 11:52:08] app-docker.js not running. +[2025-03-30 11:52:10] app-docker.js not running. +[2025-03-30 11:52:12] app-docker.js not running. +[2025-03-30 11:52:14] app-docker.js not running. +[2025-03-30 11:52:16] app-docker.js not running. +[2025-03-30 11:52:18] app-docker.js not running. +[2025-03-30 11:52:20] app-docker.js not running. +[2025-03-30 11:52:22] app-docker.js not running. +[2025-03-30 11:52:24] app-docker.js not running. +[2025-03-30 11:52:26] app-docker.js not running. +[2025-03-30 11:52:28] app-docker.js not running. +[2025-03-30 11:52:30] app-docker.js not running. +[2025-03-30 11:52:32] app-docker.js not running. +[2025-03-30 11:52:34] app-docker.js not running. +[2025-03-30 11:52:36] app-docker.js not running. +[2025-03-30 11:52:38] app-docker.js not running. +[2025-03-30 11:52:40] app-docker.js not running. +[2025-03-30 11:52:42] app-docker.js not running. +[2025-03-30 11:52:44] app-docker.js not running. +[2025-03-30 11:52:46] app-docker.js not running. +[2025-03-30 11:52:48] app-docker.js not running. +[2025-03-30 11:52:50] app-docker.js not running. +[2025-03-30 11:52:52] app-docker.js not running. +[2025-03-30 11:52:54] app-docker.js not running. +[2025-03-30 11:52:56] app-docker.js not running. +[2025-03-30 11:52:58] app-docker.js not running. +[2025-03-30 11:53:00] app-docker.js not running. +[2025-03-30 11:53:02] app-docker.js not running. +[2025-03-30 11:53:04] app-docker.js not running. +[2025-03-30 11:53:06] app-docker.js not running. +[2025-03-30 11:53:08] app-docker.js not running. +[2025-03-30 11:53:10] app-docker.js not running. +[2025-03-30 11:53:12] app-docker.js not running. +[2025-03-30 11:53:15] app-docker.js not running. +[2025-03-30 11:53:17] app-docker.js not running. +[2025-03-30 11:53:19] app-docker.js not running. +[2025-03-30 11:53:21] app-docker.js not running. +[2025-03-30 11:53:23] app-docker.js not running. +[2025-03-30 11:54:26] ALERT: PID 142708 CPU=1% MEM=61MB | System MEM=6265MB +[2025-03-30 11:54:26] 🔪 Killing app-docker.js (PID 142708) +[2025-03-30 11:54:26] app-docker.js killed. +[2025-03-30 11:54:26] ℹ️ No stress script running. +[2025-03-30 11:54:27] SYSTEM ALERT: Total memory usage = 6265MB +[2025-03-30 11:54:29] app-docker.js not running. +[2025-03-30 11:54:31] app-docker.js not running. +[2025-03-30 11:54:33] app-docker.js not running. +[2025-03-30 11:54:35] app-docker.js not running. +[2025-03-30 11:54:37] app-docker.js not running. +[2025-03-30 11:54:39] app-docker.js not running. +[2025-03-30 11:54:41] app-docker.js not running. +[2025-03-30 11:54:43] app-docker.js not running. +[2025-03-30 11:54:45] app-docker.js not running. +[2025-03-30 11:54:47] app-docker.js not running. +[2025-03-30 11:54:49] app-docker.js not running. +[2025-03-30 11:54:51] app-docker.js not running. +[2025-03-30 11:54:53] app-docker.js not running. +[2025-03-30 11:54:55] app-docker.js not running. +[2025-03-30 11:54:57] app-docker.js not running. +[2025-03-30 11:54:59] app-docker.js not running. +[2025-03-30 11:55:01] app-docker.js not running. +[2025-03-30 11:55:03] app-docker.js not running. +[2025-03-30 11:55:05] app-docker.js not running. +[2025-03-30 11:55:07] app-docker.js not running. +[2025-03-30 11:55:09] app-docker.js not running. +[2025-03-30 11:55:11] app-docker.js not running. +[2025-03-30 11:55:13] app-docker.js not running. +[2025-03-30 11:55:15] app-docker.js not running. +[2025-03-30 11:55:17] app-docker.js not running. +[2025-03-30 11:55:19] app-docker.js not running. +[2025-03-30 11:55:21] app-docker.js not running. +[2025-03-30 11:55:23] app-docker.js not running. +[2025-03-30 11:55:25] app-docker.js not running. +[2025-03-30 11:55:28] app-docker.js not running. +[2025-03-30 11:55:30] app-docker.js not running. +[2025-03-30 11:55:32] app-docker.js not running. +[2025-03-30 11:55:34] app-docker.js not running. +[2025-03-30 11:55:36] app-docker.js not running. +[2025-03-30 11:55:38] app-docker.js not running. +[2025-03-30 11:55:40] app-docker.js not running. +[2025-03-30 11:55:42] app-docker.js not running. +[2025-03-30 11:55:44] app-docker.js not running. +[2025-03-30 11:55:46] app-docker.js not running. +[2025-03-30 11:55:48] app-docker.js not running. +[2025-03-30 11:55:50] app-docker.js not running. +[2025-03-30 11:55:52] app-docker.js not running. +[2025-03-30 11:55:54] app-docker.js not running. +[2025-03-30 11:55:56] app-docker.js not running. +[2025-03-30 11:55:58] app-docker.js not running. +[2025-03-30 11:56:00] app-docker.js not running. +[2025-03-30 11:56:02] app-docker.js not running. +[2025-03-30 11:56:04] app-docker.js not running. +[2025-03-30 11:56:06] app-docker.js not running. +[2025-03-30 11:56:08] app-docker.js not running. +[2025-03-30 11:56:10] app-docker.js not running. +[2025-03-30 11:56:12] app-docker.js not running. +[2025-03-30 11:56:14] app-docker.js not running. +[2025-03-30 11:56:16] app-docker.js not running. +[2025-03-30 11:56:18] app-docker.js not running. +[2025-03-30 11:56:20] app-docker.js not running. +[2025-03-30 11:56:22] app-docker.js not running. +[2025-03-30 11:56:24] app-docker.js not running. +[2025-03-30 11:56:26] app-docker.js not running. +[2025-03-30 11:56:28] app-docker.js not running. +[2025-03-30 11:56:30] app-docker.js not running. +[2025-03-30 11:56:33] app-docker.js not running. +[2025-03-30 11:56:35] app-docker.js not running. +[2025-03-30 11:56:37] app-docker.js not running. +[2025-03-30 11:56:39] app-docker.js not running. +[2025-03-30 11:56:41] app-docker.js not running. +[2025-03-30 11:56:43] app-docker.js not running. +[2025-03-30 11:56:45] app-docker.js not running. +[2025-03-30 11:56:47] app-docker.js not running. +[2025-03-30 11:56:49] app-docker.js not running. +[2025-03-30 11:56:51] app-docker.js not running. +[2025-03-30 11:56:53] app-docker.js not running. +[2025-03-30 11:56:55] app-docker.js not running. +[2025-03-30 11:56:57] app-docker.js not running. +[2025-03-30 11:56:59] app-docker.js not running. +[2025-03-30 11:57:01] app-docker.js not running. +[2025-03-30 11:57:03] app-docker.js not running. +[2025-03-30 11:57:05] app-docker.js not running. +[2025-03-30 11:57:07] app-docker.js not running. +[2025-03-30 11:57:09] app-docker.js not running. +[2025-03-30 11:57:11] app-docker.js not running. +[2025-03-30 11:57:13] app-docker.js not running. +[2025-03-30 11:57:15] app-docker.js not running. +[2025-03-30 11:57:17] app-docker.js not running. +[2025-03-30 11:57:19] app-docker.js not running. +[2025-03-30 11:57:21] app-docker.js not running. +[2025-03-30 11:57:23] app-docker.js not running. +[2025-03-30 11:57:25] app-docker.js not running. +[2025-03-30 11:57:27] app-docker.js not running. +[2025-03-30 11:57:29] app-docker.js not running. +[2025-03-30 11:57:31] app-docker.js not running. +[2025-03-30 11:57:33] app-docker.js not running. +[2025-03-30 11:57:35] app-docker.js not running. +[2025-03-30 11:57:37] app-docker.js not running. +[2025-03-30 11:57:40] app-docker.js not running. +[2025-03-30 11:57:42] app-docker.js not running. +[2025-03-30 11:57:44] app-docker.js not running. +[2025-03-30 11:57:46] app-docker.js not running. +[2025-03-30 11:57:48] app-docker.js not running. +[2025-03-30 11:57:50] app-docker.js not running. +[2025-03-30 11:57:52] app-docker.js not running. +[2025-03-30 11:57:54] app-docker.js not running. +[2025-03-30 11:57:56] app-docker.js not running. +[2025-03-30 11:57:58] app-docker.js not running. +[2025-03-30 11:58:00] app-docker.js not running. +[2025-03-30 11:58:02] app-docker.js not running. +[2025-03-30 11:58:04] app-docker.js not running. +[2025-03-30 11:58:06] app-docker.js not running. +[2025-03-30 11:58:08] app-docker.js not running. +[2025-03-30 11:58:10] app-docker.js not running. +[2025-03-30 11:58:12] app-docker.js not running. +[2025-03-30 11:58:14] app-docker.js not running. +[2025-03-30 11:58:16] app-docker.js not running. +[2025-03-30 11:58:18] app-docker.js not running. +[2025-03-30 11:58:20] app-docker.js not running. +[2025-03-30 11:58:22] app-docker.js not running. +[2025-03-30 11:58:24] app-docker.js not running. +[2025-03-30 11:58:26] app-docker.js not running. +[2025-03-30 11:58:28] app-docker.js not running. +[2025-03-30 11:58:30] app-docker.js not running. +[2025-03-30 11:58:32] app-docker.js not running. +[2025-03-30 11:58:34] app-docker.js not running. +[2025-03-30 11:58:36] app-docker.js not running. +[2025-03-30 11:58:38] app-docker.js not running. +[2025-03-30 11:58:40] app-docker.js not running. +[2025-03-30 11:58:42] app-docker.js not running. +[2025-03-30 11:58:45] app-docker.js not running. +[2025-03-30 11:58:47] app-docker.js not running. +[2025-03-30 11:58:49] app-docker.js not running. +[2025-03-30 11:58:51] app-docker.js not running. +[2025-03-30 11:58:53] app-docker.js not running. +[2025-03-30 11:58:55] app-docker.js not running. +[2025-03-30 11:58:57] app-docker.js not running. +[2025-03-30 11:58:59] app-docker.js not running. +[2025-03-30 11:59:01] app-docker.js not running. +[2025-03-30 11:59:03] app-docker.js not running. +[2025-03-30 11:59:05] app-docker.js not running. +[2025-03-30 11:59:07] app-docker.js not running. +[2025-03-30 11:59:09] app-docker.js not running. +[2025-03-30 11:59:11] app-docker.js not running. +[2025-03-30 11:59:13] app-docker.js not running. +[2025-03-30 11:59:15] app-docker.js not running. +[2025-03-30 11:59:17] app-docker.js not running. +[2025-03-30 11:59:19] app-docker.js not running. +[2025-03-30 11:59:21] app-docker.js not running. +[2025-03-30 11:59:23] app-docker.js not running. +[2025-03-30 11:59:25] app-docker.js not running. +[2025-03-30 11:59:27] app-docker.js not running. +[2025-03-30 11:59:29] app-docker.js not running. +[2025-03-30 11:59:31] app-docker.js not running. +[2025-03-30 11:59:33] app-docker.js not running. +[2025-03-30 11:59:35] app-docker.js not running. +[2025-03-30 11:59:37] app-docker.js not running. +[2025-03-30 11:59:39] app-docker.js not running. +[2025-03-30 11:59:41] app-docker.js not running. +[2025-03-30 11:59:43] app-docker.js not running. +[2025-03-30 11:59:45] app-docker.js not running. +[2025-03-30 11:59:47] app-docker.js not running. +[2025-03-30 11:59:49] app-docker.js not running. +[2025-03-30 11:59:52] app-docker.js not running. +[2025-03-30 11:59:54] app-docker.js not running. +[2025-03-30 11:59:56] app-docker.js not running. +[2025-03-30 11:59:58] app-docker.js not running. +[2025-03-30 12:00:00] app-docker.js not running. +[2025-03-30 12:00:02] app-docker.js not running. +[2025-03-30 12:00:04] app-docker.js not running. +[2025-03-30 12:00:06] app-docker.js not running. +[2025-03-30 12:00:08] app-docker.js not running. +[2025-03-30 12:00:10] app-docker.js not running. +[2025-03-30 12:00:12] app-docker.js not running. +[2025-03-30 12:00:14] app-docker.js not running. +[2025-03-30 12:00:16] app-docker.js not running. +[2025-03-30 12:00:18] app-docker.js not running. +[2025-03-30 12:00:20] app-docker.js not running. +[2025-03-30 12:00:22] app-docker.js not running. +[2025-03-30 12:00:24] app-docker.js not running. +[2025-03-30 12:00:26] app-docker.js not running. +[2025-03-30 12:00:28] app-docker.js not running. +[2025-03-30 12:00:30] app-docker.js not running. +[2025-03-30 12:00:32] app-docker.js not running. +[2025-03-30 12:00:34] app-docker.js not running. +[2025-03-30 12:00:36] app-docker.js not running. +[2025-03-30 12:00:38] app-docker.js not running. +[2025-03-30 12:00:40] app-docker.js not running. +[2025-03-30 12:00:42] app-docker.js not running. +[2025-03-30 12:00:44] app-docker.js not running. +[2025-03-30 12:00:46] app-docker.js not running. +[2025-03-30 12:00:48] app-docker.js not running. +[2025-03-30 12:00:50] app-docker.js not running. +[2025-03-30 12:00:52] app-docker.js not running. +[2025-03-30 12:00:54] app-docker.js not running. +[2025-03-30 12:00:56] app-docker.js not running. +[2025-03-30 12:00:58] app-docker.js not running. +[2025-03-30 12:01:00] app-docker.js not running. +[2025-03-30 12:01:03] app-docker.js not running. +[2025-03-30 12:01:05] app-docker.js not running. +[2025-03-30 12:01:07] app-docker.js not running. +[2025-03-30 12:01:09] app-docker.js not running. +[2025-03-30 12:01:11] app-docker.js not running. +[2025-03-30 12:01:13] app-docker.js not running. +[2025-03-30 12:01:15] app-docker.js not running. +[2025-03-30 12:01:17] app-docker.js not running. +[2025-03-30 12:01:19] app-docker.js not running. +[2025-03-30 12:01:21] app-docker.js not running. +[2025-03-30 12:01:23] app-docker.js not running. +[2025-03-30 12:01:25] app-docker.js not running. +[2025-03-30 12:01:27] app-docker.js not running. +[2025-03-30 12:01:29] app-docker.js not running. +[2025-03-30 12:01:31] app-docker.js not running. +[2025-03-30 12:01:33] app-docker.js not running. +[2025-03-30 12:01:35] app-docker.js not running. +[2025-03-30 12:01:37] app-docker.js not running. +[2025-03-30 12:01:39] app-docker.js not running. +[2025-03-30 12:01:41] app-docker.js not running. +[2025-03-30 12:01:43] app-docker.js not running. +[2025-03-30 12:01:45] app-docker.js not running. +[2025-03-30 12:01:47] app-docker.js not running. +[2025-03-30 12:01:49] app-docker.js not running. +[2025-03-30 12:01:51] app-docker.js not running. +[2025-03-30 12:01:53] app-docker.js not running. +[2025-03-30 12:01:55] app-docker.js not running. +[2025-03-30 12:01:57] app-docker.js not running. +[2025-03-30 12:01:59] app-docker.js not running. +[2025-03-30 12:02:01] app-docker.js not running. +[2025-03-30 12:02:03] app-docker.js not running. +[2025-03-30 12:02:05] app-docker.js not running. +[2025-03-30 12:02:07] app-docker.js not running. +[2025-03-30 12:02:09] app-docker.js not running. +[2025-03-30 12:02:11] app-docker.js not running. +[2025-03-30 12:02:13] app-docker.js not running. +[2025-03-30 12:02:15] app-docker.js not running. +[2025-03-30 12:02:17] app-docker.js not running. +[2025-03-30 12:02:20] app-docker.js not running. +[2025-03-30 12:02:22] app-docker.js not running. +[2025-03-30 12:02:24] app-docker.js not running. +[2025-03-30 12:02:26] app-docker.js not running. +[2025-03-30 12:02:28] app-docker.js not running. +[2025-03-30 12:02:30] app-docker.js not running. +[2025-03-30 12:02:32] app-docker.js not running. +[2025-03-30 12:02:34] app-docker.js not running. +[2025-03-30 12:02:36] app-docker.js not running. +[2025-03-30 12:02:38] app-docker.js not running. +[2025-03-30 12:02:40] app-docker.js not running. +[2025-03-30 12:02:42] app-docker.js not running. +[2025-03-30 12:02:44] app-docker.js not running. +[2025-03-30 12:02:46] app-docker.js not running. +[2025-03-30 12:02:48] app-docker.js not running. +[2025-03-30 12:02:50] app-docker.js not running. +[2025-03-30 12:02:52] app-docker.js not running. +[2025-03-30 12:02:54] app-docker.js not running. +[2025-03-30 12:02:56] app-docker.js not running. +[2025-03-30 12:02:58] app-docker.js not running. +[2025-03-30 12:03:00] app-docker.js not running. +[2025-03-30 12:03:02] app-docker.js not running. +[2025-03-30 12:03:04] app-docker.js not running. +[2025-03-30 12:03:06] app-docker.js not running. +[2025-03-30 12:03:08] app-docker.js not running. +[2025-03-30 12:03:10] app-docker.js not running. +[2025-03-30 12:03:12] app-docker.js not running. +[2025-03-30 12:03:14] app-docker.js not running. +[2025-03-30 12:03:16] app-docker.js not running. +[2025-03-30 12:03:18] app-docker.js not running. +[2025-03-30 12:03:20] app-docker.js not running. +[2025-03-30 12:03:22] app-docker.js not running. +[2025-03-30 12:03:24] app-docker.js not running. +[2025-03-30 12:03:26] app-docker.js not running. +[2025-03-30 12:03:28] app-docker.js not running. +[2025-03-30 12:03:30] app-docker.js not running. +[2025-03-30 12:03:32] app-docker.js not running. +[2025-03-30 12:03:34] app-docker.js not running. +[2025-03-30 12:03:37] app-docker.js not running. +[2025-03-30 12:03:39] app-docker.js not running. +[2025-03-30 12:03:41] app-docker.js not running. +[2025-03-30 12:03:43] app-docker.js not running. +[2025-03-30 12:03:45] app-docker.js not running. +[2025-03-30 12:03:47] app-docker.js not running. +[2025-03-30 12:03:49] app-docker.js not running. +[2025-03-30 12:03:51] app-docker.js not running. +[2025-03-30 12:03:53] app-docker.js not running. +[2025-03-30 12:03:55] app-docker.js not running. +[2025-03-30 12:03:57] app-docker.js not running. +[2025-03-30 12:03:59] app-docker.js not running. +[2025-03-30 12:04:01] app-docker.js not running. +[2025-03-30 12:04:03] app-docker.js not running. +[2025-03-30 12:04:05] app-docker.js not running. +[2025-03-30 12:04:07] app-docker.js not running. +[2025-03-30 12:04:09] app-docker.js not running. +[2025-03-30 12:04:11] app-docker.js not running. +[2025-03-30 12:04:13] app-docker.js not running. +[2025-03-30 12:04:15] app-docker.js not running. +[2025-03-30 12:04:17] app-docker.js not running. +[2025-03-30 12:04:19] app-docker.js not running. +[2025-03-30 12:04:21] app-docker.js not running. +[2025-03-30 12:04:23] app-docker.js not running. +[2025-03-30 12:04:25] app-docker.js not running. +[2025-03-30 12:04:27] app-docker.js not running. +[2025-03-30 12:04:29] app-docker.js not running. +[2025-03-30 12:04:31] app-docker.js not running. +[2025-03-30 12:04:33] app-docker.js not running. +[2025-03-30 12:04:35] app-docker.js not running. +[2025-03-30 12:04:37] app-docker.js not running. +[2025-03-30 12:04:39] app-docker.js not running. +[2025-03-30 12:04:41] app-docker.js not running. +[2025-03-30 12:04:43] app-docker.js not running. +[2025-03-30 12:04:45] app-docker.js not running. +[2025-03-30 12:04:47] app-docker.js not running. +[2025-03-30 12:04:49] app-docker.js not running. +[2025-03-30 12:04:51] app-docker.js not running. +[2025-03-30 12:04:53] app-docker.js not running. +[2025-03-30 12:04:56] app-docker.js not running. +[2025-03-30 12:04:58] app-docker.js not running. +[2025-03-30 12:05:00] app-docker.js not running. +[2025-03-30 12:05:02] app-docker.js not running. +[2025-03-30 12:05:04] app-docker.js not running. +[2025-03-30 12:05:06] app-docker.js not running. +[2025-03-30 12:05:08] app-docker.js not running. +[2025-03-30 12:05:10] app-docker.js not running. +[2025-03-30 12:05:12] app-docker.js not running. +[2025-03-30 12:05:14] app-docker.js not running. +[2025-03-30 12:05:16] app-docker.js not running. +[2025-03-30 12:05:18] app-docker.js not running. +[2025-03-30 12:05:20] app-docker.js not running. +[2025-03-30 12:05:22] app-docker.js not running. +[2025-03-30 12:05:24] app-docker.js not running. +[2025-03-30 12:05:26] app-docker.js not running. +[2025-03-30 12:05:28] app-docker.js not running. +[2025-03-30 12:05:30] app-docker.js not running. +[2025-03-30 12:05:32] app-docker.js not running. +[2025-03-30 12:05:34] app-docker.js not running. +[2025-03-30 12:05:36] app-docker.js not running. +[2025-03-30 12:05:38] app-docker.js not running. +[2025-03-30 12:05:40] app-docker.js not running. +[2025-03-30 12:05:42] app-docker.js not running. +[2025-03-30 12:05:44] app-docker.js not running. +[2025-03-30 12:05:46] app-docker.js not running. +[2025-03-30 12:05:48] app-docker.js not running. +[2025-03-30 12:05:50] app-docker.js not running. +[2025-03-30 12:05:52] app-docker.js not running. +[2025-03-30 12:05:54] app-docker.js not running. +[2025-03-30 12:05:56] app-docker.js not running. +[2025-03-30 12:05:58] app-docker.js not running. +[2025-03-30 12:06:00] app-docker.js not running. +[2025-03-30 12:06:02] app-docker.js not running. +[2025-03-30 12:06:04] app-docker.js not running. +[2025-03-30 12:06:06] app-docker.js not running. +[2025-03-30 12:06:08] app-docker.js not running. +[2025-03-30 12:06:10] app-docker.js not running. +[2025-03-30 12:06:13] app-docker.js not running. +[2025-03-30 12:06:15] app-docker.js not running. +[2025-03-30 12:06:17] app-docker.js not running. +[2025-03-30 12:06:19] app-docker.js not running. +[2025-03-30 12:06:21] app-docker.js not running. +[2025-03-30 12:06:23] app-docker.js not running. +[2025-03-30 12:06:25] app-docker.js not running. +[2025-03-30 12:06:27] app-docker.js not running. +[2025-03-30 12:06:29] app-docker.js not running. +[2025-03-30 12:06:31] app-docker.js not running. +[2025-03-30 12:06:33] app-docker.js not running. +[2025-03-30 12:06:35] app-docker.js not running. +[2025-03-30 12:06:37] app-docker.js not running. +[2025-03-30 12:06:39] app-docker.js not running. +[2025-03-30 12:06:41] app-docker.js not running. +[2025-03-30 12:06:43] app-docker.js not running. +[2025-03-30 12:06:45] app-docker.js not running. +[2025-03-30 12:06:47] app-docker.js not running. +[2025-03-30 12:06:49] app-docker.js not running. +[2025-03-30 12:06:51] app-docker.js not running. +[2025-03-30 12:06:53] app-docker.js not running. +[2025-03-30 12:06:55] app-docker.js not running. +[2025-03-30 12:06:57] app-docker.js not running. +[2025-03-30 12:06:59] app-docker.js not running. +[2025-03-30 12:07:01] app-docker.js not running. +[2025-03-30 12:07:03] app-docker.js not running. +[2025-03-30 12:07:05] app-docker.js not running. +[2025-03-30 12:07:07] app-docker.js not running. +[2025-03-30 12:07:09] app-docker.js not running. +[2025-03-30 12:07:11] app-docker.js not running. +[2025-03-30 12:07:13] app-docker.js not running. +[2025-03-30 12:07:15] app-docker.js not running. +[2025-03-30 12:07:17] app-docker.js not running. +[2025-03-30 12:07:19] app-docker.js not running. +[2025-03-30 12:07:21] app-docker.js not running. +[2025-03-30 12:07:23] app-docker.js not running. +[2025-03-30 12:07:25] app-docker.js not running. +[2025-03-30 12:07:27] app-docker.js not running. +[2025-03-30 12:07:30] app-docker.js not running. +[2025-03-30 12:07:32] app-docker.js not running. +[2025-03-30 12:07:34] app-docker.js not running. +[2025-03-30 12:07:36] app-docker.js not running. +[2025-03-30 12:07:38] app-docker.js not running. +[2025-03-30 12:07:40] app-docker.js not running. +[2025-03-30 12:07:42] app-docker.js not running. +[2025-03-30 12:07:44] app-docker.js not running. +[2025-03-30 12:07:46] app-docker.js not running. +[2025-03-30 12:07:48] app-docker.js not running. +[2025-03-30 12:07:50] app-docker.js not running. +[2025-03-30 12:07:52] app-docker.js not running. +[2025-03-30 12:07:54] app-docker.js not running. +[2025-03-30 12:07:56] app-docker.js not running. +[2025-03-30 12:07:58] app-docker.js not running. +[2025-03-30 12:08:00] app-docker.js not running. +[2025-03-30 12:08:02] app-docker.js not running. +[2025-03-30 12:08:04] app-docker.js not running. +[2025-03-30 12:08:06] app-docker.js not running. +[2025-03-30 12:08:08] app-docker.js not running. +[2025-03-30 12:08:10] app-docker.js not running. +[2025-03-30 12:08:12] app-docker.js not running. +[2025-03-30 12:08:14] app-docker.js not running. +[2025-03-30 12:08:16] app-docker.js not running. +[2025-03-30 12:08:18] app-docker.js not running. +[2025-03-30 12:08:20] app-docker.js not running. +[2025-03-30 12:08:22] app-docker.js not running. +[2025-03-30 12:08:24] app-docker.js not running. +[2025-03-30 12:08:26] app-docker.js not running. +[2025-03-30 12:08:28] app-docker.js not running. +[2025-03-30 12:08:30] app-docker.js not running. +[2025-03-30 12:08:32] app-docker.js not running. +[2025-03-30 12:08:34] app-docker.js not running. +[2025-03-30 12:08:36] app-docker.js not running. +[2025-03-30 12:08:38] app-docker.js not running. +[2025-03-30 12:08:40] app-docker.js not running. +[2025-03-30 12:08:42] app-docker.js not running. +[2025-03-30 12:08:45] app-docker.js not running. +[2025-03-30 12:08:47] app-docker.js not running. +[2025-03-30 12:08:49] app-docker.js not running. +[2025-03-30 12:08:51] app-docker.js not running. +[2025-03-30 12:08:53] app-docker.js not running. +[2025-03-30 12:08:55] app-docker.js not running. +[2025-03-30 12:08:57] app-docker.js not running. +[2025-03-30 12:08:59] app-docker.js not running. +[2025-03-30 12:09:01] app-docker.js not running. +[2025-03-30 12:09:03] app-docker.js not running. +[2025-03-30 12:09:05] app-docker.js not running. +[2025-03-30 12:09:07] app-docker.js not running. +[2025-03-30 12:09:09] app-docker.js not running. +[2025-03-30 12:09:11] app-docker.js not running. +[2025-03-30 12:09:13] app-docker.js not running. +[2025-03-30 12:09:15] app-docker.js not running. +[2025-03-30 12:09:17] app-docker.js not running. +[2025-03-30 12:09:19] app-docker.js not running. +[2025-03-30 12:09:21] app-docker.js not running. +[2025-03-30 12:09:23] app-docker.js not running. +[2025-03-30 12:09:25] app-docker.js not running. +[2025-03-30 12:09:27] app-docker.js not running. +[2025-03-30 12:09:29] app-docker.js not running. +[2025-03-30 12:09:31] app-docker.js not running. +[2025-03-30 12:09:33] app-docker.js not running. +[2025-03-30 12:09:35] app-docker.js not running. +[2025-03-30 12:09:37] app-docker.js not running. +[2025-03-30 12:09:39] app-docker.js not running. +[2025-03-30 12:09:41] app-docker.js not running. +[2025-03-30 12:09:43] app-docker.js not running. +[2025-03-30 12:09:45] app-docker.js not running. +[2025-03-30 12:09:47] app-docker.js not running. +[2025-03-30 12:09:49] app-docker.js not running. +[2025-03-30 12:09:51] app-docker.js not running. +[2025-03-30 12:09:53] app-docker.js not running. +[2025-03-30 12:09:55] app-docker.js not running. +[2025-03-30 12:09:57] app-docker.js not running. +[2025-03-30 12:09:59] app-docker.js not running. +[2025-03-30 12:10:02] app-docker.js not running. +[2025-03-30 12:10:04] app-docker.js not running. +[2025-03-30 12:10:06] app-docker.js not running. +[2025-03-30 12:10:08] app-docker.js not running. +[2025-03-30 12:10:10] app-docker.js not running. +[2025-03-30 12:10:12] app-docker.js not running. +[2025-03-30 12:10:14] app-docker.js not running. +[2025-03-30 12:10:16] app-docker.js not running. +[2025-03-30 12:10:18] app-docker.js not running. +[2025-03-30 12:10:20] app-docker.js not running. +[2025-03-30 12:10:22] app-docker.js not running. +[2025-03-30 12:10:24] app-docker.js not running. +[2025-03-30 12:10:26] app-docker.js not running. +[2025-03-30 12:10:28] app-docker.js not running. +[2025-03-30 12:10:30] app-docker.js not running. +[2025-03-30 12:10:32] app-docker.js not running. +[2025-03-30 12:10:34] app-docker.js not running. +[2025-03-30 12:10:36] app-docker.js not running. +[2025-03-30 12:10:38] app-docker.js not running. +[2025-03-30 12:10:40] app-docker.js not running. +[2025-03-30 12:10:42] app-docker.js not running. +[2025-03-30 12:10:44] app-docker.js not running. +[2025-03-30 12:10:46] app-docker.js not running. +[2025-03-30 12:10:48] app-docker.js not running. +[2025-03-30 12:10:50] app-docker.js not running. +[2025-03-30 12:10:52] app-docker.js not running. +[2025-03-30 12:10:54] app-docker.js not running. +[2025-03-30 12:10:56] app-docker.js not running. +[2025-03-30 12:10:58] app-docker.js not running. +[2025-03-30 12:11:00] app-docker.js not running. +[2025-03-30 12:11:02] app-docker.js not running. +[2025-03-30 12:11:04] app-docker.js not running. +[2025-03-30 12:11:06] app-docker.js not running. +[2025-03-30 12:11:08] app-docker.js not running. +[2025-03-30 12:11:10] app-docker.js not running. +[2025-03-30 12:11:12] app-docker.js not running. +[2025-03-30 12:11:14] app-docker.js not running. +[2025-03-30 12:11:17] app-docker.js not running. +[2025-03-30 12:11:19] app-docker.js not running. +[2025-03-30 12:11:21] app-docker.js not running. +[2025-03-30 12:11:23] app-docker.js not running. +[2025-03-30 12:11:25] app-docker.js not running. +[2025-03-30 12:11:27] app-docker.js not running. +[2025-03-30 12:11:29] app-docker.js not running. +[2025-03-30 12:11:31] app-docker.js not running. +[2025-03-30 12:11:33] app-docker.js not running. +[2025-03-30 12:11:35] app-docker.js not running. +[2025-03-30 12:11:37] app-docker.js not running. +[2025-03-30 12:11:39] app-docker.js not running. +[2025-03-30 12:11:41] app-docker.js not running. +[2025-03-30 12:11:43] app-docker.js not running. +[2025-03-30 12:11:45] app-docker.js not running. +[2025-03-30 12:11:47] app-docker.js not running. +[2025-03-30 12:11:49] app-docker.js not running. +[2025-03-30 12:11:51] app-docker.js not running. +[2025-03-30 12:11:53] app-docker.js not running. +[2025-03-30 12:11:55] app-docker.js not running. +[2025-03-30 12:11:57] app-docker.js not running. +[2025-03-30 12:11:59] app-docker.js not running. +[2025-03-30 12:12:01] app-docker.js not running. +[2025-03-30 12:12:03] app-docker.js not running. +[2025-03-30 12:12:05] app-docker.js not running. +[2025-03-30 12:12:07] app-docker.js not running. +[2025-03-30 12:12:09] app-docker.js not running. +[2025-03-30 12:12:11] app-docker.js not running. +[2025-03-30 12:12:13] app-docker.js not running. +[2025-03-30 12:12:15] app-docker.js not running. +[2025-03-30 12:12:17] app-docker.js not running. +[2025-03-30 12:12:19] app-docker.js not running. +[2025-03-30 12:12:21] app-docker.js not running. +[2025-03-30 12:12:23] app-docker.js not running. +[2025-03-30 12:12:25] app-docker.js not running. +[2025-03-30 12:12:27] app-docker.js not running. +[2025-03-30 12:12:29] app-docker.js not running. +[2025-03-30 12:12:32] app-docker.js not running. +[2025-03-30 12:12:34] app-docker.js not running. +[2025-03-30 12:12:36] app-docker.js not running. +[2025-03-30 12:12:38] app-docker.js not running. +[2025-03-30 12:12:40] app-docker.js not running. +[2025-03-30 12:12:42] app-docker.js not running. +[2025-03-30 12:12:44] app-docker.js not running. +[2025-03-30 12:12:46] app-docker.js not running. +[2025-03-30 12:12:48] app-docker.js not running. +[2025-03-30 12:12:50] app-docker.js not running. +[2025-03-30 12:12:52] app-docker.js not running. +[2025-03-30 12:12:54] app-docker.js not running. +[2025-03-30 12:12:56] app-docker.js not running. +[2025-03-30 12:12:58] app-docker.js not running. +[2025-03-30 12:13:00] app-docker.js not running. +[2025-03-30 12:13:02] app-docker.js not running. +[2025-03-30 12:13:04] app-docker.js not running. +[2025-03-30 12:13:06] app-docker.js not running. +[2025-03-30 12:13:08] app-docker.js not running. +[2025-03-30 12:13:10] app-docker.js not running. +[2025-03-30 12:13:12] app-docker.js not running. +[2025-03-30 12:13:14] app-docker.js not running. +[2025-03-30 12:13:16] app-docker.js not running. +[2025-03-30 12:13:18] app-docker.js not running. +[2025-03-30 12:13:20] app-docker.js not running. +[2025-03-30 12:13:22] app-docker.js not running. +[2025-03-30 12:13:24] app-docker.js not running. +[2025-03-30 12:13:26] app-docker.js not running. +[2025-03-30 12:13:28] app-docker.js not running. +[2025-03-30 12:13:30] app-docker.js not running. +[2025-03-30 12:13:32] app-docker.js not running. +[2025-03-30 12:13:34] app-docker.js not running. +[2025-03-30 12:13:36] app-docker.js not running. +[2025-03-30 12:13:38] app-docker.js not running. +[2025-03-30 12:13:40] app-docker.js not running. +[2025-03-30 12:13:42] app-docker.js not running. +[2025-03-30 12:13:44] app-docker.js not running. +[2025-03-30 12:13:46] app-docker.js not running. +[2025-03-30 12:13:48] app-docker.js not running. +[2025-03-30 12:13:51] app-docker.js not running. +[2025-03-30 12:13:53] app-docker.js not running. +[2025-03-30 12:13:55] app-docker.js not running. +[2025-03-30 12:13:57] app-docker.js not running. +[2025-03-30 12:13:59] app-docker.js not running. +[2025-03-30 12:14:01] app-docker.js not running. +[2025-03-30 12:14:03] app-docker.js not running. +[2025-03-30 12:14:05] app-docker.js not running. +[2025-03-30 12:14:07] app-docker.js not running. +[2025-03-30 12:14:09] app-docker.js not running. +[2025-03-30 12:14:11] app-docker.js not running. +[2025-03-30 12:14:13] app-docker.js not running. +[2025-03-30 12:14:15] app-docker.js not running. +[2025-03-30 12:14:17] app-docker.js not running. +[2025-03-30 12:14:19] app-docker.js not running. +[2025-03-30 12:14:21] app-docker.js not running. +[2025-03-30 12:14:23] app-docker.js not running. +[2025-03-30 12:14:25] app-docker.js not running. +[2025-03-30 12:14:27] app-docker.js not running. +[2025-03-30 12:14:29] app-docker.js not running. +[2025-03-30 12:14:31] app-docker.js not running. +[2025-03-30 12:14:33] app-docker.js not running. +[2025-03-30 12:14:35] app-docker.js not running. +[2025-03-30 12:14:37] app-docker.js not running. +[2025-03-30 12:14:39] app-docker.js not running. +[2025-03-30 12:14:41] app-docker.js not running. +[2025-03-30 12:14:43] app-docker.js not running. +[2025-03-30 12:14:45] app-docker.js not running. +[2025-03-30 12:14:47] app-docker.js not running. +[2025-03-30 12:14:49] app-docker.js not running. +[2025-03-30 12:14:51] app-docker.js not running. +[2025-03-30 12:14:53] app-docker.js not running. +[2025-03-30 12:14:55] app-docker.js not running. +[2025-03-30 12:14:57] app-docker.js not running. +[2025-03-30 12:14:59] app-docker.js not running. +[2025-03-30 12:15:01] app-docker.js not running. +[2025-03-30 12:15:03] app-docker.js not running. +[2025-03-30 12:15:06] app-docker.js not running. +[2025-03-30 12:15:08] app-docker.js not running. +[2025-03-30 12:15:10] app-docker.js not running. +[2025-03-30 12:15:12] app-docker.js not running. +[2025-03-30 12:15:14] app-docker.js not running. +[2025-03-30 12:15:16] app-docker.js not running. +[2025-03-30 12:15:18] app-docker.js not running. +[2025-03-30 12:15:20] app-docker.js not running. +[2025-03-30 12:15:22] app-docker.js not running. +[2025-03-30 12:15:24] app-docker.js not running. +[2025-03-30 12:15:26] app-docker.js not running. +[2025-03-30 12:15:28] app-docker.js not running. +[2025-03-30 12:15:30] app-docker.js not running. +[2025-03-30 12:15:32] app-docker.js not running. +[2025-03-30 12:15:34] app-docker.js not running. +[2025-03-30 12:15:36] app-docker.js not running. +[2025-03-30 12:15:38] app-docker.js not running. +[2025-03-30 12:15:40] app-docker.js not running. +[2025-03-30 12:15:42] app-docker.js not running. +[2025-03-30 12:15:44] app-docker.js not running. +[2025-03-30 12:15:46] app-docker.js not running. +[2025-03-30 12:15:48] app-docker.js not running. +[2025-03-30 12:15:50] app-docker.js not running. +[2025-03-30 12:15:52] app-docker.js not running. +[2025-03-30 12:15:54] app-docker.js not running. +[2025-03-30 12:15:56] app-docker.js not running. +[2025-03-30 12:15:58] app-docker.js not running. +[2025-03-30 12:16:00] app-docker.js not running. +[2025-03-30 12:16:02] app-docker.js not running. +[2025-03-30 12:16:04] app-docker.js not running. +[2025-03-30 12:16:06] app-docker.js not running. +[2025-03-30 12:16:08] app-docker.js not running. +[2025-03-30 12:16:10] app-docker.js not running. +[2025-03-30 12:16:12] app-docker.js not running. +[2025-03-30 12:16:14] app-docker.js not running. +[2025-03-30 12:16:16] app-docker.js not running. +[2025-03-30 12:16:18] app-docker.js not running. +[2025-03-30 12:16:20] app-docker.js not running. +[2025-03-30 12:16:23] app-docker.js not running. +[2025-03-30 12:16:25] app-docker.js not running. +[2025-03-30 12:16:27] app-docker.js not running. +[2025-03-30 12:16:29] app-docker.js not running. +[2025-03-30 12:16:31] app-docker.js not running. +[2025-03-30 12:16:33] app-docker.js not running. +[2025-03-30 12:16:35] app-docker.js not running. +[2025-03-30 12:16:37] app-docker.js not running. +[2025-03-30 12:16:39] app-docker.js not running. +[2025-03-30 12:16:41] app-docker.js not running. +[2025-03-30 12:16:43] app-docker.js not running. +[2025-03-30 12:16:45] app-docker.js not running. +[2025-03-30 12:16:47] app-docker.js not running. +[2025-03-30 12:16:49] app-docker.js not running. +[2025-03-30 12:16:51] app-docker.js not running. +[2025-03-30 12:16:53] app-docker.js not running. +[2025-03-30 12:16:55] app-docker.js not running. +[2025-03-30 12:16:57] app-docker.js not running. +[2025-03-30 12:16:59] app-docker.js not running. +[2025-03-30 12:17:01] app-docker.js not running. +[2025-03-30 12:17:03] app-docker.js not running. +[2025-03-30 12:17:05] app-docker.js not running. +[2025-03-30 12:17:07] app-docker.js not running. +[2025-03-30 12:17:09] app-docker.js not running. +[2025-03-30 12:17:11] app-docker.js not running. +[2025-03-30 12:17:13] app-docker.js not running. +[2025-03-30 12:17:15] app-docker.js not running. +[2025-03-30 12:17:17] app-docker.js not running. +[2025-03-30 12:17:19] app-docker.js not running. +[2025-03-30 12:17:21] app-docker.js not running. +[2025-03-30 12:17:23] app-docker.js not running. +[2025-03-30 12:17:25] app-docker.js not running. +[2025-03-30 12:17:27] app-docker.js not running. +[2025-03-30 12:17:29] app-docker.js not running. +[2025-03-30 12:17:31] app-docker.js not running. +[2025-03-30 12:17:33] app-docker.js not running. +[2025-03-30 12:17:35] app-docker.js not running. +[2025-03-30 12:17:37] app-docker.js not running. +[2025-03-30 12:17:40] app-docker.js not running. +[2025-03-30 12:17:42] app-docker.js not running. +[2025-03-30 12:17:44] app-docker.js not running. +[2025-03-30 12:17:46] app-docker.js not running. +[2025-03-30 12:17:48] app-docker.js not running. +[2025-03-30 12:17:50] app-docker.js not running. +[2025-03-30 12:17:52] app-docker.js not running. +[2025-03-30 12:17:54] app-docker.js not running. +[2025-03-30 12:17:56] app-docker.js not running. +[2025-03-30 12:17:58] app-docker.js not running. +[2025-03-30 12:18:00] app-docker.js not running. +[2025-03-30 12:18:02] app-docker.js not running. +[2025-03-30 12:18:04] app-docker.js not running. +[2025-03-30 12:18:06] app-docker.js not running. +[2025-03-30 12:18:08] app-docker.js not running. +[2025-03-30 12:18:10] app-docker.js not running. +[2025-03-30 12:18:12] app-docker.js not running. +[2025-03-30 12:18:14] app-docker.js not running. +[2025-03-30 12:18:16] app-docker.js not running. +[2025-03-30 12:18:18] app-docker.js not running. +[2025-03-30 12:18:20] app-docker.js not running. +[2025-03-30 12:18:22] app-docker.js not running. +[2025-03-30 12:18:24] app-docker.js not running. +[2025-03-30 12:18:26] app-docker.js not running. +[2025-03-30 12:18:28] app-docker.js not running. +[2025-03-30 12:18:30] app-docker.js not running. +[2025-03-30 12:18:32] app-docker.js not running. +[2025-03-30 12:18:34] app-docker.js not running. +[2025-03-30 12:18:36] app-docker.js not running. +[2025-03-30 12:18:38] app-docker.js not running. +[2025-03-30 12:18:40] app-docker.js not running. +[2025-03-30 12:18:42] app-docker.js not running. +[2025-03-30 12:18:44] app-docker.js not running. +[2025-03-30 12:18:46] app-docker.js not running. +[2025-03-30 12:18:48] app-docker.js not running. +[2025-03-30 12:18:50] app-docker.js not running. +[2025-03-30 12:18:52] app-docker.js not running. +[2025-03-30 12:18:55] app-docker.js not running. +[2025-03-30 12:18:57] app-docker.js not running. +[2025-03-30 12:18:59] app-docker.js not running. +[2025-03-30 12:19:01] app-docker.js not running. +[2025-03-30 12:19:03] app-docker.js not running. +[2025-03-30 12:19:05] app-docker.js not running. +[2025-03-30 12:19:07] app-docker.js not running. +[2025-03-30 12:19:09] app-docker.js not running. +[2025-03-30 12:19:11] app-docker.js not running. +[2025-03-30 12:19:13] app-docker.js not running. +[2025-03-30 12:19:15] app-docker.js not running. +[2025-03-30 12:19:17] app-docker.js not running. +[2025-03-30 12:19:19] app-docker.js not running. +[2025-03-30 12:19:21] app-docker.js not running. +[2025-03-30 12:19:23] app-docker.js not running. +[2025-03-30 12:19:25] app-docker.js not running. +[2025-03-30 12:19:27] app-docker.js not running. +[2025-03-30 12:19:29] app-docker.js not running. +[2025-03-30 12:19:31] app-docker.js not running. +[2025-03-30 12:19:33] app-docker.js not running. +[2025-03-30 12:19:35] app-docker.js not running. +[2025-03-30 12:19:37] app-docker.js not running. +[2025-03-30 12:19:39] app-docker.js not running. +[2025-03-30 12:19:41] app-docker.js not running. +[2025-03-30 12:19:43] app-docker.js not running. +[2025-03-30 12:19:45] app-docker.js not running. +[2025-03-30 12:19:47] app-docker.js not running. +[2025-03-30 12:19:49] app-docker.js not running. +[2025-03-30 12:19:51] app-docker.js not running. +[2025-03-30 12:19:53] app-docker.js not running. +[2025-03-30 12:19:55] app-docker.js not running. +[2025-03-30 12:19:57] app-docker.js not running. +[2025-03-30 12:19:59] app-docker.js not running. +[2025-03-30 12:20:01] app-docker.js not running. +[2025-03-30 12:20:03] app-docker.js not running. +[2025-03-30 12:20:05] app-docker.js not running. +[2025-03-30 12:20:08] app-docker.js not running. +[2025-03-30 12:20:10] app-docker.js not running. +[2025-03-30 12:20:12] app-docker.js not running. +[2025-03-30 12:20:14] app-docker.js not running. +[2025-03-30 12:20:16] app-docker.js not running. +[2025-03-30 12:20:18] app-docker.js not running. +[2025-03-30 12:20:20] app-docker.js not running. +[2025-03-30 12:20:22] app-docker.js not running. +[2025-03-30 12:20:24] app-docker.js not running. +[2025-03-30 12:20:26] app-docker.js not running. +[2025-03-30 12:20:28] app-docker.js not running. +[2025-03-30 12:20:30] app-docker.js not running. +[2025-03-30 12:20:32] app-docker.js not running. +[2025-03-30 12:20:34] app-docker.js not running. +[2025-03-30 12:20:36] app-docker.js not running. +[2025-03-30 12:20:38] app-docker.js not running. +[2025-03-30 12:20:40] app-docker.js not running. +[2025-03-30 12:20:42] app-docker.js not running. +[2025-03-30 12:20:44] app-docker.js not running. +[2025-03-30 12:20:46] app-docker.js not running. +[2025-03-30 12:20:48] app-docker.js not running. +[2025-03-30 12:20:50] app-docker.js not running. +[2025-03-30 12:20:52] app-docker.js not running. +[2025-03-30 12:20:54] app-docker.js not running. +[2025-03-30 12:20:56] app-docker.js not running. +[2025-03-30 12:20:58] app-docker.js not running. +[2025-03-30 12:21:00] app-docker.js not running. +[2025-03-30 12:21:02] app-docker.js not running. +[2025-03-30 12:21:04] app-docker.js not running. +[2025-03-30 12:21:06] app-docker.js not running. +[2025-03-30 12:21:08] app-docker.js not running. +[2025-03-30 12:21:10] app-docker.js not running. +[2025-03-30 12:21:12] app-docker.js not running. +[2025-03-30 12:21:14] app-docker.js not running. +[2025-03-30 12:21:16] app-docker.js not running. +[2025-03-30 12:21:18] app-docker.js not running. +[2025-03-30 12:21:21] app-docker.js not running. +[2025-03-30 12:21:23] app-docker.js not running. +[2025-03-30 12:21:25] app-docker.js not running. +[2025-03-30 12:21:27] app-docker.js not running. +[2025-03-30 12:21:29] app-docker.js not running. +[2025-03-30 12:21:31] app-docker.js not running. +[2025-03-30 12:21:33] app-docker.js not running. +[2025-03-30 12:21:35] app-docker.js not running. +[2025-03-30 12:21:37] app-docker.js not running. +[2025-03-30 12:21:39] app-docker.js not running. +[2025-03-30 12:21:41] app-docker.js not running. +[2025-03-30 12:21:43] app-docker.js not running. +[2025-03-30 12:21:45] app-docker.js not running. +[2025-03-30 12:21:47] app-docker.js not running. +[2025-03-30 12:21:49] app-docker.js not running. +[2025-03-30 14:58:11] ALERT: PID 322668 CPU=0% MEM=62MB | System MEM=6004MB +[2025-03-30 14:58:11] 🔪 Killing app-docker.js (PID 322668) +[2025-03-30 14:58:11] app-docker.js killed. +[2025-03-30 14:58:11] ℹ️ No stress script running. +[2025-03-30 14:58:11] SYSTEM ALERT: Total memory usage = 6004MB +[2025-03-30 14:58:13] app-docker.js not running. +[2025-03-30 14:58:15] app-docker.js not running. +[2025-03-30 14:58:18] app-docker.js not running. +[2025-03-30 14:58:20] app-docker.js not running. +[2025-03-30 14:58:22] app-docker.js not running. +[2025-03-30 14:58:24] app-docker.js not running. +[2025-03-30 14:58:26] app-docker.js not running. +[2025-03-30 14:58:28] app-docker.js not running. +[2025-03-30 14:58:30] app-docker.js not running. +[2025-03-30 14:58:32] app-docker.js not running. +[2025-03-30 14:58:34] app-docker.js not running. +[2025-03-30 14:58:36] app-docker.js not running. +[2025-03-30 14:58:38] app-docker.js not running. +[2025-03-30 14:58:40] app-docker.js not running. +[2025-03-30 14:58:42] app-docker.js not running. +[2025-03-30 14:58:44] app-docker.js not running. +[2025-03-30 14:58:46] app-docker.js not running. +[2025-03-30 14:58:48] app-docker.js not running. +[2025-03-30 14:58:50] app-docker.js not running. +[2025-03-30 14:58:52] app-docker.js not running. +[2025-03-30 14:58:54] app-docker.js not running. +[2025-03-30 14:58:56] app-docker.js not running. +[2025-03-30 14:58:58] app-docker.js not running. +[2025-03-30 14:59:00] app-docker.js not running. +[2025-03-30 14:59:02] app-docker.js not running. +[2025-03-30 14:59:04] app-docker.js not running. +[2025-03-30 14:59:06] app-docker.js not running. +[2025-03-30 14:59:08] app-docker.js not running. +[2025-03-30 14:59:10] app-docker.js not running. +[2025-03-30 14:59:12] app-docker.js not running. +[2025-03-30 14:59:14] app-docker.js not running. +[2025-03-30 14:59:16] app-docker.js not running. +[2025-03-30 14:59:18] app-docker.js not running. +[2025-03-30 14:59:20] app-docker.js not running. +[2025-03-30 14:59:22] app-docker.js not running. +[2025-03-30 14:59:25] app-docker.js not running. +[2025-03-30 14:59:27] app-docker.js not running. +[2025-03-30 14:59:29] app-docker.js not running. +[2025-03-30 14:59:31] app-docker.js not running. +[2025-03-30 14:59:33] app-docker.js not running. +[2025-03-30 14:59:35] app-docker.js not running. +[2025-03-30 14:59:37] app-docker.js not running. +[2025-03-30 14:59:39] app-docker.js not running. +[2025-03-30 14:59:41] app-docker.js not running. +[2025-03-30 14:59:43] app-docker.js not running. +[2025-03-30 14:59:45] app-docker.js not running. +[2025-03-30 14:59:47] app-docker.js not running. +[2025-03-30 14:59:49] app-docker.js not running. +[2025-03-30 14:59:51] app-docker.js not running. +[2025-03-30 14:59:53] app-docker.js not running. +[2025-03-30 14:59:55] app-docker.js not running. +[2025-03-30 14:59:57] app-docker.js not running. +[2025-03-30 14:59:59] app-docker.js not running. +[2025-03-30 15:00:01] app-docker.js not running. +[2025-03-30 15:00:03] app-docker.js not running. +[2025-03-30 15:00:05] app-docker.js not running. +[2025-03-30 15:00:07] app-docker.js not running. +[2025-03-30 15:00:09] app-docker.js not running. +[2025-03-30 15:00:11] app-docker.js not running. +[2025-03-30 15:00:13] app-docker.js not running. +[2025-03-30 15:00:15] app-docker.js not running. +[2025-03-30 15:00:17] app-docker.js not running. +[2025-03-30 15:00:19] app-docker.js not running. +[2025-03-30 15:00:21] app-docker.js not running. +[2025-03-30 15:00:23] app-docker.js not running. +[2025-03-30 15:00:25] app-docker.js not running. +[2025-03-30 15:00:27] app-docker.js not running. +[2025-03-30 15:00:29] app-docker.js not running. +[2025-03-30 15:00:31] app-docker.js not running. +[2025-03-30 15:00:34] app-docker.js not running. +[2025-03-30 15:00:36] app-docker.js not running. +[2025-03-30 15:00:38] app-docker.js not running. +[2025-03-30 15:00:40] app-docker.js not running. +[2025-03-30 15:00:42] app-docker.js not running. +[2025-03-30 15:00:44] app-docker.js not running. +[2025-03-30 15:00:46] app-docker.js not running. +[2025-03-30 15:00:48] app-docker.js not running. +[2025-03-30 15:00:50] app-docker.js not running. +[2025-03-30 15:00:52] app-docker.js not running. +[2025-03-30 15:00:54] app-docker.js not running. +[2025-03-30 15:00:56] app-docker.js not running. +[2025-03-30 15:00:58] app-docker.js not running. +[2025-03-30 15:01:00] app-docker.js not running. +[2025-03-30 15:01:02] app-docker.js not running. +[2025-03-30 15:01:04] app-docker.js not running. +[2025-03-30 15:01:06] app-docker.js not running. +[2025-03-30 15:01:08] app-docker.js not running. +[2025-03-30 15:01:10] app-docker.js not running. +[2025-03-30 15:01:12] app-docker.js not running. +[2025-03-30 15:01:14] app-docker.js not running. +[2025-03-30 15:01:16] app-docker.js not running. +[2025-03-30 15:01:18] app-docker.js not running. +[2025-03-30 15:01:20] app-docker.js not running. +[2025-03-30 15:01:22] app-docker.js not running. +[2025-03-30 15:01:24] app-docker.js not running. +[2025-03-30 15:01:26] app-docker.js not running. +[2025-03-30 15:01:28] app-docker.js not running. +[2025-03-30 15:01:30] app-docker.js not running. +[2025-03-30 15:01:32] app-docker.js not running. +[2025-03-30 15:01:34] app-docker.js not running. +[2025-03-30 15:01:36] app-docker.js not running. +[2025-03-30 15:01:38] app-docker.js not running. +[2025-03-30 15:01:40] app-docker.js not running. +[2025-03-30 15:01:42] app-docker.js not running. +[2025-03-30 15:01:44] app-docker.js not running. +[2025-03-30 15:01:47] app-docker.js not running. +[2025-03-30 15:01:49] app-docker.js not running. +[2025-03-30 15:01:51] app-docker.js not running. +[2025-03-30 15:01:53] app-docker.js not running. +[2025-03-30 15:01:55] app-docker.js not running. +[2025-03-30 15:01:57] app-docker.js not running. +[2025-03-30 15:01:59] app-docker.js not running. +[2025-03-30 15:02:01] app-docker.js not running. +[2025-03-30 15:02:03] app-docker.js not running. +[2025-03-30 15:02:05] app-docker.js not running. +[2025-03-30 15:02:07] app-docker.js not running. +[2025-03-30 15:02:09] app-docker.js not running. +[2025-03-30 15:02:11] app-docker.js not running. +[2025-03-30 15:02:13] app-docker.js not running. +[2025-03-30 15:02:15] app-docker.js not running. +[2025-03-30 15:02:17] app-docker.js not running. +[2025-03-30 15:02:19] app-docker.js not running. +[2025-03-30 15:02:21] app-docker.js not running. +[2025-03-30 15:02:23] app-docker.js not running. +[2025-03-30 15:02:25] app-docker.js not running. +[2025-03-30 15:02:27] app-docker.js not running. +[2025-03-30 15:02:29] app-docker.js not running. +[2025-03-30 15:02:31] app-docker.js not running. +[2025-03-30 15:02:33] app-docker.js not running. +[2025-03-30 15:02:35] app-docker.js not running. +[2025-03-30 15:02:37] app-docker.js not running. +[2025-03-30 15:02:39] app-docker.js not running. +[2025-03-30 15:02:41] app-docker.js not running. +[2025-03-30 15:02:43] app-docker.js not running. +[2025-03-30 15:02:45] app-docker.js not running. +[2025-03-30 15:02:47] app-docker.js not running. +[2025-03-30 15:02:50] app-docker.js not running. +[2025-03-30 15:02:52] app-docker.js not running. +[2025-03-30 15:02:54] app-docker.js not running. +[2025-03-30 15:02:56] app-docker.js not running. +[2025-03-30 15:02:58] app-docker.js not running. +[2025-03-30 15:03:00] app-docker.js not running. +[2025-03-30 15:03:02] app-docker.js not running. +[2025-03-30 15:03:04] app-docker.js not running. +[2025-03-30 15:03:06] app-docker.js not running. +[2025-03-30 15:03:08] app-docker.js not running. +[2025-03-30 15:03:10] app-docker.js not running. +[2025-03-30 15:03:12] app-docker.js not running. +[2025-03-30 15:03:14] app-docker.js not running. +[2025-03-30 15:03:16] app-docker.js not running. +[2025-03-30 15:03:18] app-docker.js not running. +[2025-03-30 15:03:20] app-docker.js not running. +[2025-03-30 15:03:22] app-docker.js not running. +[2025-03-30 15:03:24] app-docker.js not running. +[2025-03-30 15:03:26] app-docker.js not running. +[2025-03-30 15:03:28] app-docker.js not running. +[2025-03-30 15:03:30] app-docker.js not running. +[2025-03-30 15:03:32] app-docker.js not running. +[2025-03-30 15:03:34] app-docker.js not running. +[2025-03-30 15:03:36] app-docker.js not running. +[2025-03-30 15:03:38] app-docker.js not running. +[2025-03-30 15:03:40] app-docker.js not running. +[2025-03-30 15:03:42] app-docker.js not running. +[2025-03-30 15:03:44] app-docker.js not running. +[2025-03-30 15:03:46] app-docker.js not running. +[2025-03-30 15:03:48] app-docker.js not running. +[2025-03-30 15:03:50] app-docker.js not running. +[2025-03-30 15:03:52] app-docker.js not running. +[2025-03-30 15:03:54] app-docker.js not running. +[2025-03-30 15:03:56] app-docker.js not running. +[2025-03-30 15:03:59] app-docker.js not running. +[2025-03-30 15:04:01] app-docker.js not running. +[2025-03-30 15:04:03] app-docker.js not running. +[2025-03-30 15:04:05] app-docker.js not running. +[2025-03-30 15:04:07] app-docker.js not running. +[2025-03-30 15:04:09] app-docker.js not running. +[2025-03-30 15:04:11] app-docker.js not running. +[2025-03-30 15:04:13] app-docker.js not running. +[2025-03-30 15:04:15] app-docker.js not running. +[2025-03-30 15:04:17] app-docker.js not running. +[2025-03-30 15:04:19] app-docker.js not running. +[2025-03-30 15:04:21] app-docker.js not running. +[2025-03-30 15:04:23] app-docker.js not running. +[2025-03-30 15:04:25] app-docker.js not running. +[2025-03-30 15:04:27] app-docker.js not running. +[2025-03-30 15:04:29] app-docker.js not running. +[2025-03-30 15:04:31] app-docker.js not running. +[2025-03-30 15:04:33] app-docker.js not running. +[2025-03-30 15:04:35] app-docker.js not running. +[2025-03-30 15:04:37] app-docker.js not running. +[2025-03-30 15:04:39] app-docker.js not running. +[2025-03-30 15:04:41] app-docker.js not running. +[2025-03-30 15:04:43] app-docker.js not running. +[2025-03-30 15:04:45] app-docker.js not running. +[2025-03-30 15:04:47] app-docker.js not running. +[2025-03-30 15:04:49] app-docker.js not running. +[2025-03-30 15:04:51] app-docker.js not running. +[2025-03-30 15:04:53] app-docker.js not running. +[2025-03-30 15:04:55] app-docker.js not running. +[2025-03-30 15:04:57] app-docker.js not running. +[2025-03-30 15:04:59] app-docker.js not running. +[2025-03-30 15:05:01] app-docker.js not running. +[2025-03-30 15:05:03] app-docker.js not running. +[2025-03-30 15:05:05] app-docker.js not running. +[2025-03-30 15:05:08] app-docker.js not running. +[2025-03-30 15:05:10] app-docker.js not running. +[2025-03-30 15:05:12] app-docker.js not running. +[2025-03-30 15:05:14] app-docker.js not running. +[2025-03-30 15:05:16] app-docker.js not running. +[2025-03-30 15:05:18] app-docker.js not running. +[2025-03-30 15:05:20] app-docker.js not running. +[2025-03-30 15:05:22] app-docker.js not running. +[2025-03-30 15:05:24] app-docker.js not running. +[2025-03-30 15:05:26] app-docker.js not running. +[2025-03-30 15:05:28] app-docker.js not running. +[2025-03-30 15:05:30] app-docker.js not running. +[2025-03-30 15:05:32] app-docker.js not running. +[2025-03-30 15:05:34] app-docker.js not running. +[2025-03-30 15:05:36] app-docker.js not running. +[2025-03-30 15:05:38] app-docker.js not running. +[2025-03-30 15:05:40] app-docker.js not running. +[2025-03-30 15:05:42] app-docker.js not running. +[2025-03-30 15:05:44] app-docker.js not running. +[2025-03-30 15:05:46] app-docker.js not running. +[2025-03-30 15:05:48] app-docker.js not running. +[2025-03-30 15:05:50] app-docker.js not running. +[2025-03-30 15:05:52] app-docker.js not running. +[2025-03-30 15:05:54] app-docker.js not running. +[2025-03-30 15:05:56] app-docker.js not running. +[2025-03-30 15:05:58] app-docker.js not running. +[2025-03-30 15:06:00] app-docker.js not running. +[2025-03-30 15:06:02] app-docker.js not running. +[2025-03-30 15:06:04] app-docker.js not running. +[2025-03-30 15:06:06] app-docker.js not running. +[2025-03-30 15:06:08] app-docker.js not running. +[2025-03-30 15:06:10] app-docker.js not running. +[2025-03-30 15:06:13] app-docker.js not running. +[2025-03-30 15:06:15] app-docker.js not running. +[2025-03-30 15:06:17] app-docker.js not running. +[2025-03-30 15:06:19] app-docker.js not running. +[2025-03-30 15:06:21] app-docker.js not running. +[2025-03-30 15:06:23] app-docker.js not running. +[2025-03-30 15:06:25] app-docker.js not running. +[2025-03-30 15:06:27] app-docker.js not running. +[2025-03-30 15:06:29] app-docker.js not running. +[2025-03-30 15:06:31] app-docker.js not running. +[2025-03-30 15:06:33] app-docker.js not running. +[2025-03-30 15:06:35] app-docker.js not running. +[2025-03-30 15:06:37] app-docker.js not running. +[2025-03-30 15:06:39] app-docker.js not running. +[2025-03-30 15:06:41] app-docker.js not running. +[2025-03-30 15:06:43] app-docker.js not running. +[2025-03-30 15:06:45] app-docker.js not running. +[2025-03-30 15:06:47] app-docker.js not running. +[2025-03-30 15:06:49] app-docker.js not running. +[2025-03-30 15:06:51] app-docker.js not running. +[2025-03-30 15:06:53] app-docker.js not running. +[2025-03-30 15:06:55] app-docker.js not running. +[2025-03-30 15:06:57] app-docker.js not running. +[2025-03-30 15:06:59] app-docker.js not running. +[2025-03-30 15:07:01] app-docker.js not running. +[2025-03-30 15:07:03] app-docker.js not running. +[2025-03-30 15:07:05] app-docker.js not running. +[2025-03-30 15:07:07] app-docker.js not running. +[2025-03-30 15:07:09] app-docker.js not running. +[2025-03-30 15:07:11] app-docker.js not running. +[2025-03-30 15:07:13] app-docker.js not running. +[2025-03-30 15:07:15] app-docker.js not running. +[2025-03-30 15:07:17] app-docker.js not running. +[2025-03-30 15:07:19] app-docker.js not running. +[2025-03-30 15:07:21] app-docker.js not running. +[2025-03-30 15:07:24] app-docker.js not running. +[2025-03-30 15:07:26] app-docker.js not running. +[2025-03-30 15:07:28] app-docker.js not running. +[2025-03-30 15:07:30] app-docker.js not running. +[2025-03-30 15:07:32] app-docker.js not running. +[2025-03-30 15:07:34] app-docker.js not running. +[2025-03-30 15:07:36] app-docker.js not running. +[2025-03-30 15:07:38] app-docker.js not running. +[2025-03-30 15:07:40] app-docker.js not running. +[2025-03-30 15:07:42] app-docker.js not running. +[2025-03-30 15:07:44] app-docker.js not running. +[2025-03-30 15:07:46] app-docker.js not running. +[2025-03-30 15:07:48] app-docker.js not running. +[2025-03-30 15:07:50] app-docker.js not running. +[2025-03-30 15:07:52] app-docker.js not running. +[2025-03-30 15:07:54] app-docker.js not running. +[2025-03-30 15:07:56] app-docker.js not running. +[2025-03-30 15:07:58] app-docker.js not running. +[2025-03-30 15:08:00] app-docker.js not running. +[2025-03-30 15:08:02] app-docker.js not running. +[2025-03-30 15:08:04] app-docker.js not running. +[2025-03-30 15:08:06] app-docker.js not running. +[2025-03-30 15:08:08] app-docker.js not running. +[2025-03-30 15:08:10] app-docker.js not running. +[2025-03-30 15:08:12] app-docker.js not running. +[2025-03-30 15:08:14] app-docker.js not running. +[2025-03-30 15:08:16] app-docker.js not running. +[2025-03-30 15:08:18] app-docker.js not running. +[2025-03-30 15:08:20] app-docker.js not running. +[2025-03-30 15:08:22] app-docker.js not running. +[2025-03-30 15:08:24] app-docker.js not running. +[2025-03-30 15:08:26] app-docker.js not running. +[2025-03-30 15:08:28] app-docker.js not running. +[2025-03-30 15:08:30] app-docker.js not running. +[2025-03-30 15:08:33] app-docker.js not running. +[2025-03-30 15:08:35] app-docker.js not running. +[2025-03-30 15:08:37] app-docker.js not running. +[2025-03-30 15:08:39] app-docker.js not running. +[2025-03-30 15:08:41] app-docker.js not running. +[2025-03-30 15:08:43] app-docker.js not running. +[2025-03-30 15:08:45] app-docker.js not running. +[2025-03-30 15:08:47] app-docker.js not running. +[2025-03-30 15:08:49] app-docker.js not running. +[2025-03-30 15:08:51] app-docker.js not running. +[2025-03-30 15:08:53] app-docker.js not running. +[2025-03-30 15:08:55] app-docker.js not running. +[2025-03-30 15:08:57] app-docker.js not running. +[2025-03-30 15:08:59] app-docker.js not running. +[2025-03-30 15:09:01] app-docker.js not running. +[2025-03-30 15:09:03] app-docker.js not running. +[2025-03-30 15:09:05] app-docker.js not running. +[2025-03-30 15:09:07] app-docker.js not running. +[2025-03-30 15:09:09] app-docker.js not running. +[2025-03-30 15:09:11] app-docker.js not running. +[2025-03-30 15:09:13] app-docker.js not running. +[2025-03-30 15:09:15] app-docker.js not running. +[2025-03-30 15:09:17] app-docker.js not running. +[2025-03-30 15:09:19] app-docker.js not running. +[2025-03-30 15:09:21] app-docker.js not running. +[2025-03-30 15:09:23] app-docker.js not running. +[2025-03-30 15:09:25] app-docker.js not running. +[2025-03-30 15:09:27] app-docker.js not running. +[2025-03-30 15:09:29] app-docker.js not running. +[2025-03-30 15:09:31] app-docker.js not running. +[2025-03-30 15:09:33] app-docker.js not running. +[2025-03-30 15:09:35] app-docker.js not running. +[2025-03-30 15:09:37] app-docker.js not running. +[2025-03-30 15:09:39] app-docker.js not running. +[2025-03-30 15:09:42] app-docker.js not running. +[2025-03-30 15:09:44] app-docker.js not running. +[2025-03-30 15:09:46] app-docker.js not running. +[2025-03-30 15:09:48] app-docker.js not running. +[2025-03-30 15:09:50] app-docker.js not running. +[2025-03-30 15:09:52] app-docker.js not running. +[2025-03-30 15:09:54] app-docker.js not running. +[2025-03-30 15:09:56] app-docker.js not running. +[2025-03-30 15:09:58] app-docker.js not running. +[2025-03-30 15:10:00] app-docker.js not running. +[2025-03-30 15:10:02] app-docker.js not running. +[2025-03-30 15:10:04] app-docker.js not running. +[2025-03-30 15:10:06] app-docker.js not running. +[2025-03-30 15:10:08] app-docker.js not running. +[2025-03-30 15:10:10] app-docker.js not running. +[2025-03-30 15:10:12] app-docker.js not running. +[2025-03-30 15:10:14] app-docker.js not running. +[2025-03-30 15:10:16] app-docker.js not running. +[2025-03-30 15:10:18] app-docker.js not running. +[2025-03-30 15:10:20] app-docker.js not running. +[2025-03-30 15:10:22] app-docker.js not running. +[2025-03-30 15:10:24] app-docker.js not running. +[2025-03-30 15:10:26] app-docker.js not running. +[2025-03-30 15:10:28] app-docker.js not running. +[2025-03-30 15:10:30] app-docker.js not running. +[2025-03-30 15:10:32] app-docker.js not running. +[2025-03-30 15:10:34] app-docker.js not running. +[2025-03-30 15:10:36] app-docker.js not running. +[2025-03-30 15:10:38] app-docker.js not running. +[2025-03-30 15:10:40] app-docker.js not running. +[2025-03-30 15:10:42] app-docker.js not running. +[2025-03-30 15:10:44] app-docker.js not running. +[2025-03-30 15:10:46] app-docker.js not running. +[2025-03-30 15:10:48] app-docker.js not running. +[2025-03-30 15:10:51] app-docker.js not running. +[2025-03-30 15:10:53] app-docker.js not running. +[2025-03-30 15:10:55] app-docker.js not running. +[2025-03-30 15:10:57] app-docker.js not running. +[2025-03-30 15:10:59] app-docker.js not running. +[2025-03-30 15:11:01] app-docker.js not running. +[2025-03-30 15:11:03] app-docker.js not running. +[2025-03-30 15:11:05] app-docker.js not running. +[2025-03-30 15:11:07] app-docker.js not running. +[2025-03-30 15:11:09] app-docker.js not running. +[2025-03-30 15:11:11] app-docker.js not running. +[2025-03-30 15:11:13] app-docker.js not running. +[2025-03-30 15:11:15] app-docker.js not running. +[2025-03-30 15:11:17] app-docker.js not running. +[2025-03-30 15:11:19] app-docker.js not running. +[2025-03-30 15:11:21] app-docker.js not running. +[2025-03-30 15:11:23] app-docker.js not running. +[2025-03-30 15:11:25] app-docker.js not running. +[2025-03-30 15:11:27] app-docker.js not running. +[2025-03-30 15:11:29] app-docker.js not running. +[2025-03-30 15:11:31] app-docker.js not running. +[2025-03-30 15:11:33] app-docker.js not running. +[2025-03-30 15:11:35] app-docker.js not running. +[2025-03-30 15:11:37] app-docker.js not running. +[2025-03-30 15:11:39] app-docker.js not running. +[2025-03-30 15:11:41] app-docker.js not running. +[2025-03-30 15:11:43] app-docker.js not running. +[2025-03-30 15:11:45] app-docker.js not running. +[2025-03-30 15:11:47] app-docker.js not running. +[2025-03-30 15:11:49] app-docker.js not running. +[2025-03-30 15:11:51] app-docker.js not running. +[2025-03-30 15:11:53] app-docker.js not running. +[2025-03-30 15:11:56] app-docker.js not running. +[2025-03-30 15:11:58] app-docker.js not running. +[2025-03-30 15:12:00] app-docker.js not running. +[2025-03-30 15:12:02] app-docker.js not running. +[2025-03-30 15:12:04] app-docker.js not running. +[2025-03-30 15:12:06] app-docker.js not running. +[2025-03-30 15:12:08] app-docker.js not running. +[2025-03-30 15:12:10] app-docker.js not running. +[2025-03-30 15:12:12] app-docker.js not running. +[2025-03-30 15:12:14] app-docker.js not running. +[2025-03-30 15:12:16] app-docker.js not running. +[2025-03-30 15:12:18] app-docker.js not running. +[2025-03-30 15:12:20] app-docker.js not running. +[2025-03-30 15:12:22] app-docker.js not running. +[2025-03-30 15:12:24] app-docker.js not running. +[2025-03-30 15:12:26] app-docker.js not running. +[2025-03-30 15:12:28] app-docker.js not running. +[2025-03-30 15:12:30] app-docker.js not running. +[2025-03-30 15:12:32] app-docker.js not running. +[2025-03-30 15:12:34] app-docker.js not running. +[2025-03-30 15:12:36] app-docker.js not running. +[2025-03-30 15:12:38] app-docker.js not running. +[2025-03-30 15:12:40] app-docker.js not running. +[2025-03-30 15:12:42] app-docker.js not running. +[2025-03-30 15:12:44] app-docker.js not running. +[2025-03-30 15:12:46] app-docker.js not running. +[2025-03-30 15:12:48] app-docker.js not running. +[2025-03-30 15:12:50] app-docker.js not running. +[2025-03-30 15:12:52] app-docker.js not running. +[2025-03-30 15:12:54] app-docker.js not running. +[2025-03-30 15:12:56] app-docker.js not running. +[2025-03-30 15:12:58] app-docker.js not running. +[2025-03-30 15:13:00] app-docker.js not running. +[2025-03-30 15:13:02] app-docker.js not running. +[2025-03-30 15:13:04] app-docker.js not running. +[2025-03-30 15:13:07] app-docker.js not running. +[2025-03-30 15:13:09] app-docker.js not running. +[2025-03-30 15:13:11] app-docker.js not running. +[2025-03-30 15:13:13] app-docker.js not running. +[2025-03-30 15:13:15] app-docker.js not running. +[2025-03-30 15:13:17] app-docker.js not running. +[2025-03-30 15:13:19] app-docker.js not running. +[2025-03-30 15:13:21] app-docker.js not running. +[2025-03-30 15:13:23] app-docker.js not running. +[2025-03-30 15:13:25] app-docker.js not running. +[2025-03-30 15:13:27] app-docker.js not running. +[2025-03-30 15:13:29] app-docker.js not running. +[2025-03-30 15:13:31] app-docker.js not running. +[2025-03-30 15:13:33] app-docker.js not running. +[2025-03-30 15:13:35] app-docker.js not running. +[2025-03-30 15:13:37] app-docker.js not running. +[2025-03-30 15:13:39] app-docker.js not running. +[2025-03-30 15:13:41] app-docker.js not running. +[2025-03-30 15:13:43] app-docker.js not running. +[2025-03-30 15:13:45] app-docker.js not running. +[2025-03-30 15:13:47] app-docker.js not running. +[2025-03-30 15:13:49] app-docker.js not running. +[2025-03-30 15:13:51] app-docker.js not running. +[2025-03-30 15:13:53] app-docker.js not running. +[2025-03-30 15:13:55] app-docker.js not running. +[2025-03-30 15:13:57] app-docker.js not running. +[2025-03-30 15:13:59] app-docker.js not running. +[2025-03-30 15:14:01] app-docker.js not running. +[2025-03-30 15:14:03] app-docker.js not running. +[2025-03-30 15:14:05] app-docker.js not running. +[2025-03-30 15:14:07] app-docker.js not running. +[2025-03-30 15:14:09] app-docker.js not running. +[2025-03-30 15:14:11] app-docker.js not running. +[2025-03-30 15:14:14] app-docker.js not running. +[2025-03-30 15:14:16] app-docker.js not running. +[2025-03-30 15:14:18] app-docker.js not running. +[2025-03-30 15:14:20] app-docker.js not running. +[2025-03-30 15:14:22] app-docker.js not running. +[2025-03-30 15:14:24] app-docker.js not running. +[2025-03-30 15:14:26] app-docker.js not running. +[2025-03-30 15:14:28] app-docker.js not running. +[2025-03-30 15:14:30] app-docker.js not running. +[2025-03-30 15:14:32] app-docker.js not running. +[2025-03-30 15:14:34] app-docker.js not running. +[2025-03-30 15:14:36] app-docker.js not running. +[2025-03-30 15:14:38] app-docker.js not running. +[2025-03-30 15:14:40] app-docker.js not running. +[2025-03-30 15:14:42] app-docker.js not running. +[2025-03-30 15:14:44] app-docker.js not running. +[2025-03-30 15:14:46] app-docker.js not running. +[2025-03-30 15:14:48] app-docker.js not running. +[2025-03-30 15:14:50] app-docker.js not running. +[2025-03-30 15:14:52] app-docker.js not running. +[2025-03-30 15:14:54] app-docker.js not running. +[2025-03-30 15:14:56] app-docker.js not running. +[2025-03-30 15:14:58] app-docker.js not running. +[2025-03-30 15:15:00] app-docker.js not running. +[2025-03-30 15:15:02] app-docker.js not running. +[2025-03-30 15:15:04] app-docker.js not running. +[2025-03-30 15:15:06] app-docker.js not running. +[2025-03-30 15:15:08] app-docker.js not running. +[2025-03-30 15:15:10] app-docker.js not running. +[2025-03-30 15:15:12] app-docker.js not running. +[2025-03-30 15:15:14] app-docker.js not running. +[2025-03-30 15:15:16] app-docker.js not running. +[2025-03-30 15:15:18] app-docker.js not running. +[2025-03-30 15:15:20] app-docker.js not running. +[2025-03-30 15:15:22] app-docker.js not running. +[2025-03-30 15:15:25] app-docker.js not running. +[2025-03-30 15:15:27] app-docker.js not running. +[2025-03-30 15:15:29] app-docker.js not running. +[2025-03-30 15:15:31] app-docker.js not running. +[2025-03-30 15:15:33] app-docker.js not running. +[2025-03-30 15:15:35] app-docker.js not running. +[2025-03-30 15:15:37] app-docker.js not running. +[2025-03-30 15:15:39] app-docker.js not running. +[2025-03-30 15:15:41] app-docker.js not running. +[2025-03-30 15:15:43] app-docker.js not running. +[2025-03-30 15:15:45] app-docker.js not running. +[2025-03-30 15:15:47] app-docker.js not running. +[2025-03-30 15:15:49] app-docker.js not running. +[2025-03-30 15:15:51] app-docker.js not running. +[2025-03-30 15:15:53] app-docker.js not running. +[2025-03-30 15:15:55] app-docker.js not running. +[2025-03-30 15:15:57] app-docker.js not running. +[2025-03-30 15:15:59] app-docker.js not running. +[2025-03-30 15:16:01] app-docker.js not running. +[2025-03-30 15:16:03] app-docker.js not running. +[2025-03-30 15:16:05] app-docker.js not running. +[2025-03-30 15:16:07] app-docker.js not running. +[2025-03-30 15:16:09] app-docker.js not running. +[2025-03-30 15:16:11] app-docker.js not running. +[2025-03-30 15:16:13] app-docker.js not running. +[2025-03-30 15:16:15] app-docker.js not running. +[2025-03-30 15:16:17] app-docker.js not running. +[2025-03-30 15:16:19] app-docker.js not running. +[2025-03-30 15:16:21] app-docker.js not running. +[2025-03-30 15:16:23] app-docker.js not running. +[2025-03-30 15:16:25] app-docker.js not running. +[2025-03-30 15:16:27] app-docker.js not running. +[2025-03-30 15:16:29] app-docker.js not running. +[2025-03-30 15:16:31] app-docker.js not running. +[2025-03-30 15:16:34] app-docker.js not running. +[2025-03-30 15:16:36] app-docker.js not running. +[2025-03-30 15:16:38] app-docker.js not running. +[2025-03-30 15:16:40] app-docker.js not running. +[2025-03-30 15:16:42] app-docker.js not running. +[2025-03-30 15:16:44] app-docker.js not running. +[2025-03-30 15:16:46] app-docker.js not running. +[2025-03-30 15:16:48] app-docker.js not running. +[2025-03-30 15:16:50] app-docker.js not running. +[2025-03-30 15:16:52] app-docker.js not running. +[2025-03-30 15:16:54] app-docker.js not running. +[2025-03-30 15:16:56] app-docker.js not running. +[2025-03-30 15:16:58] app-docker.js not running. +[2025-03-30 15:17:00] app-docker.js not running. +[2025-03-30 15:17:02] app-docker.js not running. +[2025-03-30 15:17:04] app-docker.js not running. +[2025-03-30 15:17:06] app-docker.js not running. +[2025-03-30 15:17:08] app-docker.js not running. +[2025-03-30 15:17:10] app-docker.js not running. +[2025-03-30 15:17:12] app-docker.js not running. +[2025-03-30 15:17:14] app-docker.js not running. +[2025-03-30 15:17:16] app-docker.js not running. +[2025-03-30 15:17:18] app-docker.js not running. +[2025-03-30 15:17:20] app-docker.js not running. +[2025-03-30 15:17:22] app-docker.js not running. +[2025-03-30 15:17:24] app-docker.js not running. +[2025-03-30 15:17:26] app-docker.js not running. +[2025-03-30 15:17:28] app-docker.js not running. +[2025-03-30 15:17:30] app-docker.js not running. +[2025-03-30 15:17:32] app-docker.js not running. +[2025-03-30 15:17:34] app-docker.js not running. +[2025-03-30 15:17:36] app-docker.js not running. +[2025-03-30 15:17:38] app-docker.js not running. +[2025-03-30 15:17:40] app-docker.js not running. +[2025-03-30 15:17:42] app-docker.js not running. +[2025-03-30 15:17:45] app-docker.js not running. +[2025-03-30 15:17:47] app-docker.js not running. +[2025-03-30 15:17:49] app-docker.js not running. +[2025-03-30 15:17:51] app-docker.js not running. +[2025-03-30 15:17:53] app-docker.js not running. +[2025-03-30 15:17:55] app-docker.js not running. +[2025-03-30 15:17:57] app-docker.js not running. +[2025-03-30 15:17:59] app-docker.js not running. +[2025-03-30 15:18:01] app-docker.js not running. +[2025-03-30 15:18:03] app-docker.js not running. +[2025-03-30 15:18:05] app-docker.js not running. +[2025-03-30 15:18:07] app-docker.js not running. +[2025-03-30 15:18:09] app-docker.js not running. +[2025-03-30 15:18:11] app-docker.js not running. +[2025-03-30 15:18:13] app-docker.js not running. +[2025-03-30 15:18:15] app-docker.js not running. +[2025-03-30 15:18:17] app-docker.js not running. +[2025-03-30 15:18:19] app-docker.js not running. +[2025-03-30 15:18:21] app-docker.js not running. +[2025-03-30 15:18:23] app-docker.js not running. +[2025-03-30 15:18:25] app-docker.js not running. +[2025-03-30 15:18:27] app-docker.js not running. +[2025-03-30 15:18:29] app-docker.js not running. +[2025-03-30 15:18:31] app-docker.js not running. +[2025-03-30 15:18:33] app-docker.js not running. +[2025-03-30 15:18:35] app-docker.js not running. +[2025-03-30 15:18:37] app-docker.js not running. +[2025-03-30 15:18:39] app-docker.js not running. +[2025-03-30 15:18:41] app-docker.js not running. +[2025-03-30 15:18:43] app-docker.js not running. +[2025-03-30 15:18:45] app-docker.js not running. +[2025-03-30 15:18:47] app-docker.js not running. +[2025-03-30 15:18:50] app-docker.js not running. +[2025-03-30 15:18:52] app-docker.js not running. +[2025-03-30 15:18:54] app-docker.js not running. +[2025-03-30 15:18:56] app-docker.js not running. +[2025-03-30 15:18:58] app-docker.js not running. +[2025-03-30 15:19:00] app-docker.js not running. +[2025-03-30 15:19:02] app-docker.js not running. +[2025-03-30 15:19:04] app-docker.js not running. +[2025-03-30 15:19:06] app-docker.js not running. +[2025-03-30 15:19:08] app-docker.js not running. +[2025-03-30 15:19:10] app-docker.js not running. +[2025-03-30 15:19:12] app-docker.js not running. +[2025-03-30 15:19:14] app-docker.js not running. +[2025-03-30 15:19:16] app-docker.js not running. +[2025-03-30 15:19:18] app-docker.js not running. +[2025-03-30 15:19:20] app-docker.js not running. +[2025-03-30 15:19:22] app-docker.js not running. +[2025-03-30 15:19:24] app-docker.js not running. +[2025-03-30 15:19:26] app-docker.js not running. +[2025-03-30 15:19:28] app-docker.js not running. +[2025-03-30 15:19:30] app-docker.js not running. +[2025-03-30 15:19:32] app-docker.js not running. +[2025-03-30 15:19:34] app-docker.js not running. +[2025-03-30 15:19:36] app-docker.js not running. +[2025-03-30 15:19:38] app-docker.js not running. +[2025-03-30 15:19:40] app-docker.js not running. +[2025-03-30 15:19:42] app-docker.js not running. +[2025-03-30 15:19:44] app-docker.js not running. +[2025-03-30 15:19:46] app-docker.js not running. +[2025-03-30 15:19:48] app-docker.js not running. +[2025-03-30 15:19:50] app-docker.js not running. +[2025-03-30 15:19:52] app-docker.js not running. +[2025-03-30 15:19:54] app-docker.js not running. +[2025-03-30 15:19:56] app-docker.js not running. +[2025-03-30 15:19:59] app-docker.js not running. +[2025-03-30 15:20:01] app-docker.js not running. +[2025-03-30 15:20:03] app-docker.js not running. +[2025-03-30 15:20:05] app-docker.js not running. +[2025-03-30 15:20:07] app-docker.js not running. +[2025-03-30 15:20:09] app-docker.js not running. +[2025-03-30 15:20:11] app-docker.js not running. +[2025-03-30 15:20:13] app-docker.js not running. +[2025-03-30 15:20:15] app-docker.js not running. +[2025-03-30 15:20:17] app-docker.js not running. +[2025-03-30 15:20:19] app-docker.js not running. +[2025-03-30 15:20:21] app-docker.js not running. +[2025-03-30 15:20:23] app-docker.js not running. +[2025-03-30 15:20:25] app-docker.js not running. +[2025-03-30 15:20:27] app-docker.js not running. +[2025-03-30 15:20:29] app-docker.js not running. +[2025-03-30 15:20:31] app-docker.js not running. +[2025-03-30 15:20:33] app-docker.js not running. +[2025-03-30 15:20:35] app-docker.js not running. +[2025-03-30 15:20:37] app-docker.js not running. +[2025-03-30 15:20:39] app-docker.js not running. +[2025-03-30 15:20:41] app-docker.js not running. +[2025-03-30 15:20:43] app-docker.js not running. +[2025-03-30 15:20:45] app-docker.js not running. +[2025-03-30 15:20:47] app-docker.js not running. +[2025-03-30 15:20:49] app-docker.js not running. +[2025-03-30 15:20:51] app-docker.js not running. +[2025-03-30 15:20:53] app-docker.js not running. +[2025-03-30 15:20:55] app-docker.js not running. +[2025-03-30 15:20:57] app-docker.js not running. +[2025-03-30 15:20:59] app-docker.js not running. +[2025-03-30 15:21:01] app-docker.js not running. +[2025-03-30 15:21:03] app-docker.js not running. +[2025-03-30 15:21:05] app-docker.js not running. +[2025-03-30 15:21:07] app-docker.js not running. +[2025-03-30 15:21:09] app-docker.js not running. +[2025-03-30 15:21:12] app-docker.js not running. +[2025-03-30 15:21:14] app-docker.js not running. +[2025-03-30 15:21:16] app-docker.js not running. +[2025-03-30 15:21:18] app-docker.js not running. +[2025-03-30 15:21:20] app-docker.js not running. +[2025-03-30 15:21:22] app-docker.js not running. +[2025-03-30 15:21:24] app-docker.js not running. +[2025-03-30 15:21:26] app-docker.js not running. +[2025-03-30 15:21:28] app-docker.js not running. +[2025-03-30 15:21:30] app-docker.js not running. +[2025-03-30 15:21:32] app-docker.js not running. +[2025-03-30 15:21:34] app-docker.js not running. +[2025-03-30 15:21:36] app-docker.js not running. +[2025-03-30 15:21:38] app-docker.js not running. +[2025-03-30 15:21:40] app-docker.js not running. +[2025-03-30 15:21:42] app-docker.js not running. +[2025-03-30 15:21:44] app-docker.js not running. +[2025-03-30 15:21:46] app-docker.js not running. +[2025-03-30 15:21:48] app-docker.js not running. +[2025-03-30 15:21:50] app-docker.js not running. +[2025-03-30 15:21:52] app-docker.js not running. +[2025-03-30 15:21:54] app-docker.js not running. +[2025-03-30 15:21:56] app-docker.js not running. +[2025-03-30 15:21:58] app-docker.js not running. +[2025-03-30 15:22:00] app-docker.js not running. +[2025-03-30 15:22:02] app-docker.js not running. +[2025-03-30 15:22:04] app-docker.js not running. +[2025-03-30 15:22:06] app-docker.js not running. +[2025-03-30 15:22:08] app-docker.js not running. +[2025-03-30 15:22:10] app-docker.js not running. +[2025-03-30 15:22:12] app-docker.js not running. +[2025-03-30 15:22:14] app-docker.js not running. +[2025-03-30 15:22:16] app-docker.js not running. +[2025-03-30 15:22:18] app-docker.js not running. +[2025-03-30 15:22:21] app-docker.js not running. +[2025-03-30 15:22:23] app-docker.js not running. +[2025-03-30 15:22:25] app-docker.js not running. +[2025-03-30 15:22:27] app-docker.js not running. +[2025-03-30 15:22:29] app-docker.js not running. +[2025-03-30 15:22:31] app-docker.js not running. +[2025-03-30 15:22:33] app-docker.js not running. +[2025-03-30 15:22:35] app-docker.js not running. +[2025-03-30 15:22:37] app-docker.js not running. +[2025-03-30 15:22:39] app-docker.js not running. +[2025-03-30 15:22:41] app-docker.js not running. +[2025-03-30 15:22:43] app-docker.js not running. +[2025-03-30 15:22:45] app-docker.js not running. +[2025-03-30 15:22:47] app-docker.js not running. +[2025-03-30 15:22:49] app-docker.js not running. +[2025-03-30 15:22:51] app-docker.js not running. +[2025-03-30 15:22:53] app-docker.js not running. +[2025-03-30 15:22:55] app-docker.js not running. +[2025-03-30 15:22:57] app-docker.js not running. +[2025-03-30 15:22:59] app-docker.js not running. +[2025-03-30 15:23:01] app-docker.js not running. +[2025-03-30 15:23:03] app-docker.js not running. +[2025-03-30 15:23:05] app-docker.js not running. +[2025-03-30 15:23:07] app-docker.js not running. +[2025-03-30 15:23:09] app-docker.js not running. +[2025-03-30 15:23:11] app-docker.js not running. +[2025-03-30 15:23:13] app-docker.js not running. +[2025-03-30 15:23:15] app-docker.js not running. +[2025-03-30 15:23:17] app-docker.js not running. +[2025-03-30 15:23:19] app-docker.js not running. +[2025-03-30 15:23:21] app-docker.js not running. +[2025-03-30 15:23:23] app-docker.js not running. +[2025-03-30 15:23:25] app-docker.js not running. +[2025-03-30 15:23:27] app-docker.js not running. +[2025-03-30 15:23:29] app-docker.js not running. +[2025-03-30 15:23:32] app-docker.js not running. +[2025-03-30 15:23:34] app-docker.js not running. +[2025-03-30 15:23:36] app-docker.js not running. +[2025-03-30 15:23:38] app-docker.js not running. +[2025-03-30 15:23:40] app-docker.js not running. +[2025-03-30 15:23:42] app-docker.js not running. +[2025-03-30 15:23:44] app-docker.js not running. +[2025-03-30 15:23:46] app-docker.js not running. +[2025-03-30 15:23:48] app-docker.js not running. +[2025-03-30 15:23:50] app-docker.js not running. +[2025-03-30 15:23:52] app-docker.js not running. +[2025-03-30 15:23:54] app-docker.js not running. +[2025-03-30 15:23:56] app-docker.js not running. +[2025-03-30 15:23:58] app-docker.js not running. +[2025-03-30 15:24:00] app-docker.js not running. +[2025-03-30 15:24:02] app-docker.js not running. +[2025-03-30 15:24:04] app-docker.js not running. +[2025-03-30 15:24:06] app-docker.js not running. +[2025-03-30 15:24:08] app-docker.js not running. +[2025-03-30 15:24:10] app-docker.js not running. +[2025-03-30 15:24:12] app-docker.js not running. +[2025-03-30 15:24:14] app-docker.js not running. +[2025-03-30 15:24:16] app-docker.js not running. +[2025-03-30 15:24:18] app-docker.js not running. +[2025-03-30 15:24:20] app-docker.js not running. +[2025-03-30 15:24:22] app-docker.js not running. +[2025-03-30 15:24:24] app-docker.js not running. +[2025-03-30 15:24:26] app-docker.js not running. +[2025-03-30 15:24:28] app-docker.js not running. +[2025-03-30 15:24:30] app-docker.js not running. +[2025-03-30 15:24:32] app-docker.js not running. +[2025-03-30 15:24:34] app-docker.js not running. +[2025-03-30 15:24:36] app-docker.js not running. +[2025-03-30 15:24:38] app-docker.js not running. +[2025-03-30 15:24:41] app-docker.js not running. +[2025-03-30 15:24:43] app-docker.js not running. +[2025-03-30 15:24:45] app-docker.js not running. +[2025-03-30 15:24:47] app-docker.js not running. +[2025-03-30 15:24:49] app-docker.js not running. +[2025-03-30 15:24:51] app-docker.js not running. +[2025-03-30 15:24:53] app-docker.js not running. +[2025-03-30 15:24:55] app-docker.js not running. +[2025-03-30 15:24:57] app-docker.js not running. +[2025-03-30 15:24:59] app-docker.js not running. +[2025-03-30 15:25:01] app-docker.js not running. +[2025-03-30 15:25:03] app-docker.js not running. +[2025-03-30 15:25:05] app-docker.js not running. +[2025-03-30 15:25:07] app-docker.js not running. +[2025-03-30 15:25:09] app-docker.js not running. +[2025-03-30 15:25:11] app-docker.js not running. +[2025-03-30 15:25:13] app-docker.js not running. +[2025-03-30 15:25:15] app-docker.js not running. +[2025-03-30 15:25:17] app-docker.js not running. +[2025-03-30 15:25:19] app-docker.js not running. +[2025-03-30 15:25:21] app-docker.js not running. +[2025-03-30 15:25:23] app-docker.js not running. +[2025-03-30 15:25:25] app-docker.js not running. +[2025-03-30 15:25:27] app-docker.js not running. +[2025-03-30 15:25:29] app-docker.js not running. +[2025-03-30 15:25:31] app-docker.js not running. +[2025-03-30 15:25:33] app-docker.js not running. +[2025-03-30 15:25:35] app-docker.js not running. +[2025-03-30 15:25:37] app-docker.js not running. +[2025-03-30 15:25:39] app-docker.js not running. +[2025-03-30 15:25:41] app-docker.js not running. +[2025-03-30 15:25:43] app-docker.js not running. +[2025-03-30 15:25:45] app-docker.js not running. +[2025-03-30 15:25:47] app-docker.js not running. +[2025-03-30 15:25:50] app-docker.js not running. +[2025-03-30 15:25:52] app-docker.js not running. +[2025-03-30 15:25:54] app-docker.js not running. +[2025-03-30 15:25:56] app-docker.js not running. +[2025-03-30 15:25:58] app-docker.js not running. +[2025-03-30 15:26:00] app-docker.js not running. +[2025-03-30 15:26:02] app-docker.js not running. +[2025-03-30 15:26:04] app-docker.js not running. +[2025-03-30 15:26:06] app-docker.js not running. +[2025-03-30 15:26:08] app-docker.js not running. +[2025-03-30 15:26:10] app-docker.js not running. +[2025-03-30 15:26:12] app-docker.js not running. +[2025-03-30 15:26:14] app-docker.js not running. +[2025-03-30 15:26:16] app-docker.js not running. +[2025-03-30 15:26:18] app-docker.js not running. +[2025-03-30 15:26:20] app-docker.js not running. +[2025-03-30 15:26:22] app-docker.js not running. +[2025-03-30 15:26:24] app-docker.js not running. +[2025-03-30 15:26:26] app-docker.js not running. +[2025-03-30 15:26:28] app-docker.js not running. +[2025-03-30 15:26:30] app-docker.js not running. +[2025-03-30 15:26:32] app-docker.js not running. +[2025-03-30 15:26:34] app-docker.js not running. +[2025-03-30 15:26:36] app-docker.js not running. +[2025-03-30 15:26:38] app-docker.js not running. +[2025-03-30 15:26:40] app-docker.js not running. +[2025-03-30 15:26:42] app-docker.js not running. +[2025-03-30 15:26:44] app-docker.js not running. +[2025-03-30 15:26:46] app-docker.js not running. +[2025-03-30 15:26:48] app-docker.js not running. +[2025-03-30 15:26:50] app-docker.js not running. +[2025-03-30 15:26:52] app-docker.js not running. +[2025-03-30 15:26:54] app-docker.js not running. +[2025-03-30 15:26:56] app-docker.js not running. +[2025-03-30 15:26:59] app-docker.js not running. +[2025-03-30 15:27:01] app-docker.js not running. +[2025-03-30 15:27:03] app-docker.js not running. +[2025-03-30 15:27:05] app-docker.js not running. +[2025-03-30 15:27:07] app-docker.js not running. +[2025-03-30 15:27:09] app-docker.js not running. +[2025-03-30 15:27:11] app-docker.js not running. +[2025-03-30 15:27:13] app-docker.js not running. +[2025-03-30 15:27:15] app-docker.js not running. +[2025-03-30 15:27:17] app-docker.js not running. +[2025-03-30 15:27:19] app-docker.js not running. +[2025-03-30 15:27:21] app-docker.js not running. +[2025-03-30 15:27:23] app-docker.js not running. +[2025-03-30 15:27:26] app-docker.js not running. +[2025-03-30 15:32:29] app-docker.js not running. +[2025-03-30 15:32:31] app-docker.js not running. +[2025-03-30 15:32:33] app-docker.js not running. +[2025-03-30 15:32:35] app-docker.js not running. +[2025-03-30 15:32:37] app-docker.js not running. +[2025-03-30 15:32:39] app-docker.js not running. +[2025-03-30 15:32:41] app-docker.js not running. +[2025-03-30 15:32:43] app-docker.js not running. +[2025-03-30 15:32:45] app-docker.js not running. +[2025-03-30 15:32:47] app-docker.js not running. +[2025-03-30 15:32:50] app-docker.js not running. +[2025-03-30 15:32:52] app-docker.js not running. +[2025-03-30 15:32:54] app-docker.js not running. +[2025-03-30 15:32:56] app-docker.js not running. +[2025-03-30 15:32:58] app-docker.js not running. +[2025-03-30 15:33:00] app-docker.js not running. +[2025-03-30 15:33:02] app-docker.js not running. +[2025-03-30 15:33:04] app-docker.js not running. +[2025-03-30 15:33:06] app-docker.js not running. +[2025-03-30 15:33:08] app-docker.js not running. +[2025-03-30 15:33:10] app-docker.js not running. +[2025-03-30 15:33:12] app-docker.js not running. +[2025-03-30 15:33:14] app-docker.js not running. +[2025-03-30 15:33:16] app-docker.js not running. +[2025-03-30 15:33:18] app-docker.js not running. +[2025-03-30 15:33:20] app-docker.js not running. +[2025-03-30 15:33:22] app-docker.js not running. +[2025-03-30 15:33:24] app-docker.js not running. +[2025-03-30 15:33:26] app-docker.js not running. +[2025-03-30 15:33:28] app-docker.js not running. +[2025-03-30 15:33:31] app-docker.js not running. +[2025-03-30 15:33:33] app-docker.js not running. +[2025-03-30 15:33:35] app-docker.js not running. +[2025-03-30 15:33:37] app-docker.js not running. +[2025-03-30 15:33:39] app-docker.js not running. +[2025-03-30 15:33:41] app-docker.js not running. +[2025-03-30 15:33:43] app-docker.js not running. +[2025-03-30 15:33:45] app-docker.js not running. +[2025-03-30 15:33:47] app-docker.js not running. +[2025-03-30 15:33:49] app-docker.js not running. +[2025-03-30 15:33:51] app-docker.js not running. +[2025-03-30 15:33:53] app-docker.js not running. +[2025-03-30 15:33:55] app-docker.js not running. +[2025-03-30 15:33:57] app-docker.js not running. +[2025-03-30 15:33:59] app-docker.js not running. +[2025-03-30 15:34:01] app-docker.js not running. +[2025-03-30 15:34:03] app-docker.js not running. +[2025-03-30 15:34:05] app-docker.js not running. +[2025-03-30 15:34:07] app-docker.js not running. +[2025-03-30 15:34:09] app-docker.js not running. +[2025-03-30 15:34:11] app-docker.js not running. +[2025-03-30 15:34:13] app-docker.js not running. +[2025-03-30 15:34:16] app-docker.js not running. +[2025-03-30 15:34:18] app-docker.js not running. +[2025-03-30 15:34:20] app-docker.js not running. +[2025-03-30 15:34:22] app-docker.js not running. +[2025-03-30 15:34:24] app-docker.js not running. +[2025-03-30 15:34:26] app-docker.js not running. +[2025-03-30 15:34:28] app-docker.js not running. +[2025-03-30 15:34:30] app-docker.js not running. +[2025-03-30 15:34:32] app-docker.js not running. +[2025-03-30 15:34:35] app-docker.js not running. +[2025-03-30 15:34:37] app-docker.js not running. +[2025-03-30 15:34:39] app-docker.js not running. +[2025-03-30 15:34:41] app-docker.js not running. +[2025-03-30 15:34:44] app-docker.js not running. +[2025-03-30 15:34:47] app-docker.js not running. +[2025-03-30 15:50:39] app-docker.js not running. +[2025-03-30 16:26:35] app-docker.js not running. +[2025-03-30 16:26:37] app-docker.js not running. +[2025-03-30 16:26:39] app-docker.js not running. +[2025-03-30 16:26:41] app-docker.js not running. +[2025-03-30 16:26:43] app-docker.js not running. +[2025-03-30 16:26:45] app-docker.js not running. +[2025-03-30 16:26:47] app-docker.js not running. +[2025-03-30 16:26:49] app-docker.js not running. +[2025-03-30 16:26:51] app-docker.js not running. +[2025-03-30 16:26:53] app-docker.js not running. +[2025-03-30 16:26:55] app-docker.js not running. +[2025-03-30 16:26:57] app-docker.js not running. +[2025-03-30 16:26:59] app-docker.js not running. +[2025-03-30 16:27:01] app-docker.js not running. +[2025-03-30 16:27:03] app-docker.js not running. +[2025-03-30 16:27:06] app-docker.js not running. +[2025-03-30 16:27:08] app-docker.js not running. +[2025-03-30 16:27:10] app-docker.js not running. +[2025-03-30 16:27:12] app-docker.js not running. +[2025-03-30 16:27:15] app-docker.js not running. +[2025-03-30 16:27:19] app-docker.js not running. +[2025-03-30 16:27:22] app-docker.js not running. +[2025-03-30 16:29:30] app-docker.js not running. +[2025-03-30 16:40:08] app-docker.js not running. +[2025-03-30 16:40:15] app-docker.js not running. +[2025-03-30 16:42:08] app-docker.js not running. +[2025-03-30 16:42:14] app-docker.js not running. +[2025-03-30 16:42:27] app-docker.js not running. +[2025-03-30 16:42:40] app-docker.js not running. +[2025-03-30 16:45:05] app-docker.js not running. +[2025-03-30 16:45:16] app-docker.js not running. +[2025-03-30 16:49:33] app-docker.js not running. +[2025-03-30 16:52:21] app-docker.js not running. +[2025-03-30 16:52:57] app-docker.js not running. +[2025-03-30 17:18:50] app-docker.js not running. +[2025-03-30 19:27:58] app-docker.js not running. +[2025-03-30 20:33:26] app-docker.js not running. +[2025-03-30 20:33:28] app-docker.js not running. +[2025-03-30 20:33:30] app-docker.js not running. +[2025-03-30 20:33:32] app-docker.js not running. +[2025-03-30 20:33:34] app-docker.js not running. +[2025-03-30 20:33:36] app-docker.js not running. +[2025-03-30 20:33:38] app-docker.js not running. +[2025-03-30 20:33:40] app-docker.js not running. +[2025-03-30 20:33:42] app-docker.js not running. +[2025-03-30 20:33:45] app-docker.js not running. +[2025-03-30 20:33:47] app-docker.js not running. +[2025-03-30 20:33:49] app-docker.js not running. +[2025-03-30 20:33:51] app-docker.js not running. +[2025-03-30 20:33:53] app-docker.js not running. +[2025-03-30 20:33:55] app-docker.js not running. +[2025-03-30 20:33:57] app-docker.js not running. +[2025-03-30 20:33:59] app-docker.js not running. +[2025-03-30 20:34:01] app-docker.js not running. +[2025-03-30 20:34:03] app-docker.js not running. +[2025-03-30 20:34:05] app-docker.js not running. +[2025-03-30 20:34:07] app-docker.js not running. +[2025-03-30 20:34:09] app-docker.js not running. +[2025-03-30 20:34:11] app-docker.js not running. +[2025-03-30 20:34:13] app-docker.js not running. +[2025-03-30 20:34:15] app-docker.js not running. +[2025-03-30 20:34:17] app-docker.js not running. +[2025-03-30 20:34:19] app-docker.js not running. +[2025-03-30 20:34:21] app-docker.js not running. +[2025-03-30 20:34:23] app-docker.js not running. +[2025-03-30 20:34:25] app-docker.js not running. +[2025-03-30 20:34:27] app-docker.js not running. +[2025-03-30 20:34:29] app-docker.js not running. +[2025-03-30 20:34:31] app-docker.js not running. +[2025-03-30 20:34:33] app-docker.js not running. +[2025-03-30 20:34:35] app-docker.js not running. +[2025-03-30 20:34:37] app-docker.js not running. +[2025-03-30 20:34:39] app-docker.js not running. +[2025-03-30 20:34:41] app-docker.js not running. +[2025-03-30 20:34:43] app-docker.js not running. +[2025-03-30 20:34:45] app-docker.js not running. +[2025-03-30 20:34:47] app-docker.js not running. +[2025-03-30 20:34:49] app-docker.js not running. +[2025-03-30 20:34:52] app-docker.js not running. +[2025-03-30 20:34:54] app-docker.js not running. +[2025-03-30 20:34:56] app-docker.js not running. +[2025-03-30 20:34:58] app-docker.js not running. +[2025-03-30 20:35:00] app-docker.js not running. +[2025-03-30 20:35:02] app-docker.js not running. +[2025-03-30 20:35:04] app-docker.js not running. +[2025-03-30 20:35:06] app-docker.js not running. +[2025-03-30 20:35:08] app-docker.js not running. +[2025-03-30 20:35:10] app-docker.js not running. +[2025-03-30 20:35:12] app-docker.js not running. +[2025-03-30 20:35:14] app-docker.js not running. +[2025-03-30 20:35:16] app-docker.js not running. +[2025-03-30 20:35:18] app-docker.js not running. +[2025-03-30 20:35:20] app-docker.js not running. +[2025-03-30 20:35:22] app-docker.js not running. +[2025-03-30 20:35:24] app-docker.js not running. +[2025-03-30 20:35:26] app-docker.js not running. +[2025-03-30 20:35:28] app-docker.js not running. +[2025-03-30 20:35:30] app-docker.js not running. +[2025-03-30 20:35:32] app-docker.js not running. +[2025-03-30 20:35:34] app-docker.js not running. +[2025-03-30 20:35:36] app-docker.js not running. +[2025-03-30 20:35:38] app-docker.js not running. +[2025-03-30 20:35:40] app-docker.js not running. +[2025-03-30 20:35:42] app-docker.js not running. +[2025-03-30 20:35:44] app-docker.js not running. +[2025-03-30 20:35:46] app-docker.js not running. +[2025-03-30 20:35:48] app-docker.js not running. +[2025-03-30 20:35:50] app-docker.js not running. +[2025-03-30 20:35:52] app-docker.js not running. +[2025-03-30 20:35:54] app-docker.js not running. +[2025-03-30 20:35:56] app-docker.js not running. +[2025-03-30 20:35:58] app-docker.js not running. +[2025-03-30 20:36:01] app-docker.js not running. +[2025-03-30 20:36:03] app-docker.js not running. +[2025-03-30 20:36:05] app-docker.js not running. +[2025-03-30 20:36:07] app-docker.js not running. +[2025-03-30 20:36:09] app-docker.js not running. +[2025-03-30 20:36:11] app-docker.js not running. +[2025-03-30 20:36:13] app-docker.js not running. +[2025-03-30 20:36:15] app-docker.js not running. +[2025-03-30 20:36:17] app-docker.js not running. +[2025-03-30 20:36:19] app-docker.js not running. +[2025-03-30 20:36:21] app-docker.js not running. +[2025-03-30 20:36:23] app-docker.js not running. +[2025-03-30 20:36:25] app-docker.js not running. +[2025-03-30 20:36:27] app-docker.js not running. +[2025-03-30 20:36:29] app-docker.js not running. +[2025-03-30 20:36:31] app-docker.js not running. +[2025-03-30 20:36:33] app-docker.js not running. +[2025-03-30 20:36:35] app-docker.js not running. +[2025-03-30 20:36:37] app-docker.js not running. +[2025-03-30 20:36:39] app-docker.js not running. +[2025-03-30 20:36:41] app-docker.js not running. +[2025-03-30 20:36:43] app-docker.js not running. +[2025-03-30 20:36:45] app-docker.js not running. +[2025-03-30 20:36:47] app-docker.js not running. +[2025-03-30 20:36:49] app-docker.js not running. +[2025-03-30 20:36:51] app-docker.js not running. +[2025-03-30 20:36:53] app-docker.js not running. +[2025-03-30 20:36:55] app-docker.js not running. +[2025-03-30 20:36:57] app-docker.js not running. +[2025-03-30 20:36:59] app-docker.js not running. +[2025-03-30 20:37:01] app-docker.js not running. +[2025-03-30 20:37:03] app-docker.js not running. +[2025-03-30 20:37:06] app-docker.js not running. +[2025-03-30 20:37:08] app-docker.js not running. +[2025-03-30 20:37:10] app-docker.js not running. +[2025-03-30 20:37:12] app-docker.js not running. +[2025-03-30 20:37:14] app-docker.js not running. +[2025-03-30 20:37:16] app-docker.js not running. +[2025-03-30 20:37:18] app-docker.js not running. +[2025-03-30 20:37:20] app-docker.js not running. +[2025-03-30 20:37:22] app-docker.js not running. +[2025-03-30 20:37:24] app-docker.js not running. +[2025-03-30 20:37:26] app-docker.js not running. +[2025-03-30 20:37:28] app-docker.js not running. +[2025-03-30 20:37:30] app-docker.js not running. +[2025-03-30 20:37:32] app-docker.js not running. +[2025-03-30 20:37:34] app-docker.js not running. +[2025-03-30 20:37:36] app-docker.js not running. +[2025-03-30 20:37:38] app-docker.js not running. +[2025-03-30 20:37:40] app-docker.js not running. +[2025-03-30 20:37:42] app-docker.js not running. +[2025-03-30 20:37:44] app-docker.js not running. +[2025-03-30 20:37:46] app-docker.js not running. +[2025-03-30 20:37:48] app-docker.js not running. +[2025-03-30 20:37:50] app-docker.js not running. +[2025-03-30 20:37:52] app-docker.js not running. +[2025-03-30 20:37:54] app-docker.js not running. +[2025-03-30 20:37:56] app-docker.js not running. +[2025-03-30 20:37:58] app-docker.js not running. +[2025-03-30 20:38:00] app-docker.js not running. +[2025-03-30 20:38:02] app-docker.js not running. +[2025-03-30 20:38:04] app-docker.js not running. +[2025-03-30 20:38:06] app-docker.js not running. +[2025-03-30 20:38:08] app-docker.js not running. +[2025-03-30 20:38:10] app-docker.js not running. +[2025-03-30 20:38:12] app-docker.js not running. +[2025-03-30 20:38:14] app-docker.js not running. +[2025-03-30 20:38:17] app-docker.js not running. +[2025-03-30 20:38:19] app-docker.js not running. +[2025-03-30 20:38:21] app-docker.js not running. +[2025-03-30 20:38:23] app-docker.js not running. +[2025-03-30 20:38:25] app-docker.js not running. +[2025-03-30 20:38:27] app-docker.js not running. +[2025-03-30 20:38:29] app-docker.js not running. +[2025-03-30 20:38:31] app-docker.js not running. +[2025-03-30 20:38:33] app-docker.js not running. +[2025-03-30 20:38:35] app-docker.js not running. +[2025-03-30 20:38:37] app-docker.js not running. +[2025-03-30 20:38:39] app-docker.js not running. +[2025-03-30 20:38:41] app-docker.js not running. +[2025-03-30 20:38:43] app-docker.js not running. +[2025-03-30 20:38:45] app-docker.js not running. +[2025-03-30 20:38:47] app-docker.js not running. +[2025-03-30 20:38:49] app-docker.js not running. +[2025-03-30 20:38:51] app-docker.js not running. +[2025-03-30 20:38:53] app-docker.js not running. +[2025-03-30 20:38:55] app-docker.js not running. +[2025-03-30 20:38:57] app-docker.js not running. +[2025-03-30 20:38:59] app-docker.js not running. +[2025-03-30 20:39:01] app-docker.js not running. +[2025-03-30 20:39:03] app-docker.js not running. +[2025-03-30 20:39:05] app-docker.js not running. +[2025-03-30 20:39:07] app-docker.js not running. +[2025-03-30 20:39:09] app-docker.js not running. +[2025-03-30 20:39:11] app-docker.js not running. +[2025-03-30 20:39:13] app-docker.js not running. +[2025-03-30 20:39:15] app-docker.js not running. +[2025-03-30 20:39:17] app-docker.js not running. +[2025-03-30 20:39:19] app-docker.js not running. +[2025-03-30 20:39:22] app-docker.js not running. +[2025-03-30 20:39:24] app-docker.js not running. +[2025-03-30 20:39:26] app-docker.js not running. +[2025-03-30 20:39:28] app-docker.js not running. +[2025-03-30 20:39:30] app-docker.js not running. +[2025-03-30 20:39:32] app-docker.js not running. +[2025-03-30 20:39:34] app-docker.js not running. +[2025-03-30 20:39:36] app-docker.js not running. +[2025-03-30 20:39:38] app-docker.js not running. +[2025-03-30 20:39:40] app-docker.js not running. +[2025-03-30 20:39:42] app-docker.js not running. +[2025-03-30 20:39:44] app-docker.js not running. +[2025-03-30 20:39:46] app-docker.js not running. +[2025-03-30 20:39:48] app-docker.js not running. +[2025-03-30 20:39:50] app-docker.js not running. +[2025-03-30 20:39:52] app-docker.js not running. +[2025-03-30 20:39:54] app-docker.js not running. +[2025-03-30 20:39:56] app-docker.js not running. +[2025-03-30 20:39:58] app-docker.js not running. +[2025-03-30 20:40:00] app-docker.js not running. +[2025-03-30 20:40:02] app-docker.js not running. +[2025-03-30 20:40:04] app-docker.js not running. +[2025-03-30 20:40:06] app-docker.js not running. +[2025-03-30 20:40:08] app-docker.js not running. +[2025-03-30 20:40:10] app-docker.js not running. +[2025-03-30 20:40:12] app-docker.js not running. +[2025-03-30 20:40:14] app-docker.js not running. +[2025-03-30 20:40:16] app-docker.js not running. +[2025-03-30 20:40:18] app-docker.js not running. +[2025-03-30 20:40:20] app-docker.js not running. +[2025-03-30 20:40:22] app-docker.js not running. +[2025-03-30 20:40:24] app-docker.js not running. +[2025-03-30 20:40:26] app-docker.js not running. +[2025-03-30 20:40:28] app-docker.js not running. +[2025-03-30 20:40:31] app-docker.js not running. +[2025-03-30 20:40:33] app-docker.js not running. +[2025-03-30 20:40:35] app-docker.js not running. +[2025-03-30 20:40:37] app-docker.js not running. +[2025-03-30 20:40:39] app-docker.js not running. +[2025-03-30 20:40:41] app-docker.js not running. +[2025-03-30 20:40:43] app-docker.js not running. +[2025-03-30 20:40:45] app-docker.js not running. +[2025-03-30 20:40:47] app-docker.js not running. +[2025-03-30 20:40:49] app-docker.js not running. +[2025-03-30 20:40:51] app-docker.js not running. +[2025-03-30 20:40:53] app-docker.js not running. +[2025-03-30 20:40:55] app-docker.js not running. +[2025-03-30 20:40:57] app-docker.js not running. +[2025-03-30 20:40:59] app-docker.js not running. +[2025-03-30 20:41:01] app-docker.js not running. +[2025-03-30 20:41:03] app-docker.js not running. +[2025-03-30 20:41:05] app-docker.js not running. +[2025-03-30 20:41:07] app-docker.js not running. +[2025-03-30 20:41:09] app-docker.js not running. +[2025-03-30 20:41:11] app-docker.js not running. +[2025-03-30 20:41:13] app-docker.js not running. +[2025-03-30 20:41:15] app-docker.js not running. +[2025-03-30 20:41:17] app-docker.js not running. +[2025-03-30 20:41:19] app-docker.js not running. +[2025-03-30 20:41:21] app-docker.js not running. +[2025-03-30 20:41:23] app-docker.js not running. +[2025-03-30 20:41:25] app-docker.js not running. +[2025-03-30 20:41:27] app-docker.js not running. +[2025-03-30 20:41:29] app-docker.js not running. +[2025-03-30 20:41:31] app-docker.js not running. +[2025-03-30 20:41:33] app-docker.js not running. +[2025-03-30 20:41:35] app-docker.js not running. +[2025-03-30 20:41:37] app-docker.js not running. +[2025-03-30 20:41:40] app-docker.js not running. +[2025-03-30 20:41:42] app-docker.js not running. +[2025-03-30 20:41:44] app-docker.js not running. +[2025-03-30 20:41:46] app-docker.js not running. +[2025-03-30 20:41:48] app-docker.js not running. +[2025-03-30 20:41:50] app-docker.js not running. +[2025-03-30 20:41:52] app-docker.js not running. +[2025-03-30 20:41:54] app-docker.js not running. +[2025-03-30 20:41:56] app-docker.js not running. +[2025-03-30 20:41:58] app-docker.js not running. +[2025-03-30 20:42:00] app-docker.js not running. +[2025-03-30 20:42:02] app-docker.js not running. +[2025-03-30 20:42:04] app-docker.js not running. +[2025-03-30 20:42:06] app-docker.js not running. +[2025-03-30 20:42:08] app-docker.js not running. +[2025-03-30 20:42:10] app-docker.js not running. +[2025-03-30 20:42:12] app-docker.js not running. +[2025-03-30 20:42:14] app-docker.js not running. +[2025-03-30 20:42:16] app-docker.js not running. +[2025-03-30 20:42:18] app-docker.js not running. +[2025-03-30 20:42:20] app-docker.js not running. +[2025-03-30 20:42:22] app-docker.js not running. +[2025-03-30 20:42:24] app-docker.js not running. +[2025-03-30 20:42:26] app-docker.js not running. +[2025-03-30 20:42:28] app-docker.js not running. +[2025-03-30 20:42:30] app-docker.js not running. +[2025-03-30 20:42:32] app-docker.js not running. +[2025-03-30 20:42:34] app-docker.js not running. +[2025-03-30 20:42:36] app-docker.js not running. +[2025-03-30 20:42:38] app-docker.js not running. +[2025-03-30 20:42:40] app-docker.js not running. +[2025-03-30 20:42:42] app-docker.js not running. +[2025-03-30 20:42:44] app-docker.js not running. +[2025-03-30 20:42:46] app-docker.js not running. +[2025-03-30 20:42:49] app-docker.js not running. +[2025-03-30 20:42:51] app-docker.js not running. +[2025-03-30 20:42:53] app-docker.js not running. +[2025-03-30 20:42:55] app-docker.js not running. +[2025-03-30 20:42:57] app-docker.js not running. +[2025-03-30 20:42:59] app-docker.js not running. +[2025-03-30 20:43:01] app-docker.js not running. +[2025-03-30 20:43:03] app-docker.js not running. +[2025-03-30 20:43:05] app-docker.js not running. +[2025-03-30 20:43:07] app-docker.js not running. +[2025-03-30 20:43:09] app-docker.js not running. +[2025-03-30 20:43:11] app-docker.js not running. +[2025-03-30 20:43:13] app-docker.js not running. +[2025-03-30 20:43:15] app-docker.js not running. +[2025-03-30 20:43:17] app-docker.js not running. +[2025-03-30 20:43:19] app-docker.js not running. +[2025-03-30 20:43:21] app-docker.js not running. +[2025-03-30 20:43:23] app-docker.js not running. +[2025-03-30 20:43:25] app-docker.js not running. +[2025-03-30 20:43:27] app-docker.js not running. +[2025-03-30 20:43:29] app-docker.js not running. +[2025-03-30 20:43:31] app-docker.js not running. +[2025-03-30 20:43:33] app-docker.js not running. +[2025-03-30 20:43:35] app-docker.js not running. +[2025-03-30 20:43:37] app-docker.js not running. +[2025-03-30 20:43:39] app-docker.js not running. +[2025-03-30 20:43:41] app-docker.js not running. +[2025-03-30 20:43:43] app-docker.js not running. +[2025-03-30 20:43:45] app-docker.js not running. +[2025-03-30 20:43:47] app-docker.js not running. +[2025-03-30 20:43:49] app-docker.js not running. +[2025-03-30 20:43:51] app-docker.js not running. +[2025-03-30 20:43:53] app-docker.js not running. +[2025-03-30 20:43:55] app-docker.js not running. +[2025-03-30 20:43:57] app-docker.js not running. +[2025-03-30 20:44:00] app-docker.js not running. +[2025-03-30 20:44:02] app-docker.js not running. +[2025-03-30 20:44:04] app-docker.js not running. +[2025-03-30 20:44:06] app-docker.js not running. +[2025-03-30 20:44:08] app-docker.js not running. +[2025-03-30 20:44:10] app-docker.js not running. +[2025-03-30 20:44:12] app-docker.js not running. +[2025-03-30 20:44:14] app-docker.js not running. +[2025-03-30 20:44:16] app-docker.js not running. +[2025-03-30 20:44:18] app-docker.js not running. +[2025-03-30 20:44:20] app-docker.js not running. +[2025-03-30 20:44:22] app-docker.js not running. +[2025-03-30 20:44:24] app-docker.js not running. +[2025-03-30 20:44:26] app-docker.js not running. +[2025-03-30 20:44:28] app-docker.js not running. +[2025-03-30 20:44:30] app-docker.js not running. +[2025-03-30 20:44:32] app-docker.js not running. +[2025-03-30 20:44:34] app-docker.js not running. +[2025-03-30 20:44:36] app-docker.js not running. +[2025-03-30 20:44:38] app-docker.js not running. +[2025-03-30 20:44:40] app-docker.js not running. +[2025-03-30 20:44:42] app-docker.js not running. +[2025-03-30 20:44:44] app-docker.js not running. +[2025-03-30 20:44:46] app-docker.js not running. +[2025-03-30 20:44:48] app-docker.js not running. +[2025-03-30 20:44:50] app-docker.js not running. +[2025-03-30 20:44:52] app-docker.js not running. +[2025-03-30 20:44:54] app-docker.js not running. +[2025-03-30 20:44:56] app-docker.js not running. +[2025-03-30 20:44:58] app-docker.js not running. +[2025-03-30 20:45:00] app-docker.js not running. +[2025-03-30 20:45:02] app-docker.js not running. +[2025-03-30 20:45:04] app-docker.js not running. +[2025-03-30 20:45:07] app-docker.js not running. +[2025-03-30 20:45:09] app-docker.js not running. +[2025-03-30 20:45:11] app-docker.js not running. +[2025-03-30 20:45:13] app-docker.js not running. +[2025-03-30 20:45:15] app-docker.js not running. +[2025-03-30 20:45:17] app-docker.js not running. +[2025-03-30 20:45:19] app-docker.js not running. +[2025-03-30 20:45:21] app-docker.js not running. +[2025-03-30 20:45:23] app-docker.js not running. +[2025-03-30 20:45:25] app-docker.js not running. +[2025-03-30 20:45:27] app-docker.js not running. +[2025-03-30 20:45:29] app-docker.js not running. +[2025-03-30 20:45:31] app-docker.js not running. +[2025-03-30 20:45:33] app-docker.js not running. +[2025-03-30 20:45:35] app-docker.js not running. +[2025-03-30 20:45:37] app-docker.js not running. +[2025-03-30 20:45:39] app-docker.js not running. +[2025-03-30 20:45:41] app-docker.js not running. +[2025-03-30 20:45:43] app-docker.js not running. +[2025-03-30 20:45:45] app-docker.js not running. +[2025-03-30 20:45:47] app-docker.js not running. +[2025-03-30 20:45:49] app-docker.js not running. +[2025-03-30 20:45:51] app-docker.js not running. +[2025-03-30 20:45:53] app-docker.js not running. +[2025-03-30 20:45:55] app-docker.js not running. +[2025-03-30 20:45:57] app-docker.js not running. +[2025-03-30 20:45:59] app-docker.js not running. +[2025-03-30 20:46:01] app-docker.js not running. +[2025-03-30 20:46:03] app-docker.js not running. +[2025-03-30 20:46:05] app-docker.js not running. +[2025-03-30 20:46:07] app-docker.js not running. +[2025-03-30 20:46:09] app-docker.js not running. +[2025-03-30 20:46:11] app-docker.js not running. +[2025-03-30 20:46:13] app-docker.js not running. +[2025-03-30 20:46:15] app-docker.js not running. +[2025-03-30 20:46:18] app-docker.js not running. +[2025-03-30 20:46:20] app-docker.js not running. +[2025-03-30 20:46:22] app-docker.js not running. +[2025-03-30 20:46:24] app-docker.js not running. +[2025-03-30 20:46:26] app-docker.js not running. +[2025-03-30 20:46:28] app-docker.js not running. +[2025-03-30 20:46:30] app-docker.js not running. +[2025-03-30 20:46:32] app-docker.js not running. +[2025-03-30 20:46:34] app-docker.js not running. +[2025-03-30 20:46:36] app-docker.js not running. +[2025-03-30 20:46:38] app-docker.js not running. +[2025-03-30 20:46:40] app-docker.js not running. +[2025-03-30 20:46:42] app-docker.js not running. +[2025-03-30 20:46:44] app-docker.js not running. +[2025-03-30 20:46:46] app-docker.js not running. +[2025-03-30 20:46:48] app-docker.js not running. +[2025-03-30 20:46:50] app-docker.js not running. +[2025-03-30 20:46:52] app-docker.js not running. +[2025-03-30 20:46:54] app-docker.js not running. +[2025-03-30 20:46:56] app-docker.js not running. +[2025-03-30 20:46:58] app-docker.js not running. +[2025-03-30 20:47:00] app-docker.js not running. +[2025-03-30 20:47:02] app-docker.js not running. +[2025-03-30 20:47:04] app-docker.js not running. +[2025-03-30 20:47:06] app-docker.js not running. +[2025-03-30 20:47:08] app-docker.js not running. +[2025-03-30 20:47:10] app-docker.js not running. +[2025-03-30 20:47:12] app-docker.js not running. +[2025-03-30 20:47:14] app-docker.js not running. +[2025-03-30 20:47:16] app-docker.js not running. +[2025-03-30 20:47:18] app-docker.js not running. +[2025-03-30 20:47:20] app-docker.js not running. +[2025-03-30 20:47:22] app-docker.js not running. +[2025-03-30 20:47:24] app-docker.js not running. +[2025-03-30 20:47:26] app-docker.js not running. +[2025-03-30 20:47:29] app-docker.js not running. +[2025-03-30 20:47:31] app-docker.js not running. +[2025-03-30 20:47:33] app-docker.js not running. +[2025-03-30 20:47:35] app-docker.js not running. +[2025-03-30 20:47:37] app-docker.js not running. +[2025-03-30 20:47:39] app-docker.js not running. +[2025-03-30 20:47:41] app-docker.js not running. +[2025-03-30 20:47:43] app-docker.js not running. +[2025-03-30 20:47:45] app-docker.js not running. +[2025-03-30 20:47:47] app-docker.js not running. +[2025-03-30 20:47:49] app-docker.js not running. +[2025-03-30 20:47:51] app-docker.js not running. +[2025-03-30 20:47:53] app-docker.js not running. +[2025-03-30 20:47:55] app-docker.js not running. +[2025-03-30 20:47:57] app-docker.js not running. +[2025-03-30 20:47:59] app-docker.js not running. +[2025-03-30 20:48:01] app-docker.js not running. +[2025-03-30 20:48:03] app-docker.js not running. +[2025-03-30 20:48:05] app-docker.js not running. +[2025-03-30 20:48:07] app-docker.js not running. +[2025-03-30 20:48:09] app-docker.js not running. +[2025-03-30 20:48:11] app-docker.js not running. +[2025-03-30 20:48:13] app-docker.js not running. +[2025-03-30 20:48:15] app-docker.js not running. +[2025-03-30 20:48:17] app-docker.js not running. +[2025-03-30 20:48:19] app-docker.js not running. +[2025-03-30 20:48:21] app-docker.js not running. +[2025-03-30 20:48:23] app-docker.js not running. +[2025-03-30 20:48:25] app-docker.js not running. +[2025-03-30 20:48:27] app-docker.js not running. +[2025-03-30 20:48:29] app-docker.js not running. +[2025-03-30 20:48:31] app-docker.js not running. +[2025-03-30 20:48:33] app-docker.js not running. +[2025-03-30 20:48:35] app-docker.js not running. +[2025-03-30 20:48:38] app-docker.js not running. +[2025-03-30 20:48:40] app-docker.js not running. +[2025-03-30 20:48:42] app-docker.js not running. +[2025-03-30 20:48:44] app-docker.js not running. +[2025-03-30 20:48:46] app-docker.js not running. +[2025-03-30 20:48:48] app-docker.js not running. +[2025-03-30 20:48:50] app-docker.js not running. +[2025-03-30 20:48:52] app-docker.js not running. +[2025-03-30 20:48:54] app-docker.js not running. +[2025-03-30 20:48:56] app-docker.js not running. +[2025-03-30 20:48:58] app-docker.js not running. +[2025-03-30 20:49:00] app-docker.js not running. +[2025-03-30 20:49:02] app-docker.js not running. +[2025-03-30 20:49:04] app-docker.js not running. +[2025-03-30 20:49:06] app-docker.js not running. +[2025-03-30 20:49:08] app-docker.js not running. +[2025-03-30 20:49:10] app-docker.js not running. +[2025-03-30 20:49:12] app-docker.js not running. +[2025-03-30 20:49:14] app-docker.js not running. +[2025-03-30 20:49:16] app-docker.js not running. +[2025-03-30 20:49:18] app-docker.js not running. +[2025-03-30 20:49:20] app-docker.js not running. +[2025-03-30 20:49:22] app-docker.js not running. +[2025-03-30 20:49:24] app-docker.js not running. +[2025-03-30 20:49:26] app-docker.js not running. +[2025-03-30 20:49:28] app-docker.js not running. +[2025-03-30 20:49:30] app-docker.js not running. +[2025-03-30 20:49:32] app-docker.js not running. +[2025-03-30 20:49:34] app-docker.js not running. +[2025-03-30 20:49:36] app-docker.js not running. +[2025-03-30 20:49:38] app-docker.js not running. +[2025-03-30 20:49:40] app-docker.js not running. +[2025-03-30 20:49:42] app-docker.js not running. +[2025-03-30 20:49:44] app-docker.js not running. +[2025-03-30 20:49:46] app-docker.js not running. +[2025-03-30 20:49:49] app-docker.js not running. +[2025-03-30 20:49:51] app-docker.js not running. +[2025-03-30 20:49:53] app-docker.js not running. +[2025-03-30 20:49:55] app-docker.js not running. +[2025-03-30 20:49:57] app-docker.js not running. +[2025-03-30 20:49:59] app-docker.js not running. +[2025-03-30 20:50:01] app-docker.js not running. +[2025-03-30 20:50:03] app-docker.js not running. +[2025-03-30 20:50:05] app-docker.js not running. +[2025-03-30 20:50:07] app-docker.js not running. +[2025-03-30 20:50:09] app-docker.js not running. +[2025-03-30 20:50:11] app-docker.js not running. +[2025-03-30 20:50:13] app-docker.js not running. +[2025-03-30 20:50:15] app-docker.js not running. +[2025-03-30 20:50:17] app-docker.js not running. +[2025-03-30 20:50:19] app-docker.js not running. +[2025-03-30 20:50:21] app-docker.js not running. +[2025-03-30 20:50:23] app-docker.js not running. +[2025-03-30 20:50:25] app-docker.js not running. +[2025-03-30 20:50:27] app-docker.js not running. +[2025-03-30 20:50:29] app-docker.js not running. +[2025-03-30 20:50:31] app-docker.js not running. +[2025-03-30 20:50:33] app-docker.js not running. +[2025-03-30 20:50:35] app-docker.js not running. +[2025-03-30 20:50:37] app-docker.js not running. +[2025-03-30 20:50:39] app-docker.js not running. +[2025-03-30 20:50:41] app-docker.js not running. +[2025-03-30 20:50:43] app-docker.js not running. +[2025-03-30 20:50:45] app-docker.js not running. +[2025-03-30 20:50:47] app-docker.js not running. +[2025-03-30 20:50:49] app-docker.js not running. +[2025-03-30 20:50:51] app-docker.js not running. +[2025-03-30 20:50:53] app-docker.js not running. +[2025-03-30 20:50:55] app-docker.js not running. +[2025-03-30 20:50:58] app-docker.js not running. +[2025-03-30 20:51:00] app-docker.js not running. +[2025-03-30 20:51:02] app-docker.js not running. +[2025-03-30 20:51:04] app-docker.js not running. +[2025-03-30 20:51:06] app-docker.js not running. +[2025-03-30 20:51:08] app-docker.js not running. +[2025-03-30 20:51:10] app-docker.js not running. +[2025-03-30 20:51:12] app-docker.js not running. +[2025-03-30 20:51:14] app-docker.js not running. +[2025-03-30 20:51:16] app-docker.js not running. +[2025-03-30 20:51:18] app-docker.js not running. +[2025-03-30 20:51:20] app-docker.js not running. +[2025-03-30 20:51:22] app-docker.js not running. +[2025-03-30 20:51:24] app-docker.js not running. +[2025-03-30 20:51:26] app-docker.js not running. +[2025-03-30 20:51:28] app-docker.js not running. +[2025-03-30 20:51:30] app-docker.js not running. +[2025-03-30 20:51:32] app-docker.js not running. +[2025-03-30 20:51:34] app-docker.js not running. +[2025-03-30 20:51:36] app-docker.js not running. +[2025-03-30 20:51:38] app-docker.js not running. +[2025-03-30 20:51:40] app-docker.js not running. +[2025-03-30 20:51:42] app-docker.js not running. +[2025-03-30 20:51:44] app-docker.js not running. +[2025-03-30 20:51:46] app-docker.js not running. +[2025-03-30 20:51:48] app-docker.js not running. +[2025-03-30 20:51:50] app-docker.js not running. +[2025-03-30 20:51:52] app-docker.js not running. +[2025-03-30 20:51:54] app-docker.js not running. +[2025-03-30 20:51:56] app-docker.js not running. +[2025-03-30 20:51:58] app-docker.js not running. +[2025-03-30 20:52:00] app-docker.js not running. +[2025-03-30 20:52:02] app-docker.js not running. +[2025-03-30 20:52:04] app-docker.js not running. +[2025-03-30 20:52:07] app-docker.js not running. +[2025-03-30 20:52:09] app-docker.js not running. +[2025-03-30 20:52:11] app-docker.js not running. +[2025-03-30 20:52:13] app-docker.js not running. +[2025-03-30 20:52:15] app-docker.js not running. +[2025-03-30 20:52:17] app-docker.js not running. +[2025-03-30 20:52:19] app-docker.js not running. +[2025-03-30 20:52:21] app-docker.js not running. +[2025-03-30 20:52:23] app-docker.js not running. +[2025-03-30 20:52:25] app-docker.js not running. +[2025-03-30 20:52:27] app-docker.js not running. +[2025-03-30 20:52:29] app-docker.js not running. +[2025-03-30 20:52:31] app-docker.js not running. +[2025-03-30 20:52:33] app-docker.js not running. +[2025-03-30 20:52:35] app-docker.js not running. +[2025-03-30 20:52:37] app-docker.js not running. +[2025-03-30 20:52:39] app-docker.js not running. +[2025-03-30 20:52:41] app-docker.js not running. +[2025-03-30 20:52:43] app-docker.js not running. +[2025-03-30 20:52:45] app-docker.js not running. +[2025-03-30 20:52:47] app-docker.js not running. +[2025-03-30 20:52:49] app-docker.js not running. +[2025-03-30 20:52:51] app-docker.js not running. +[2025-03-30 20:52:53] app-docker.js not running. +[2025-03-30 20:52:55] app-docker.js not running. +[2025-03-30 20:52:57] app-docker.js not running. +[2025-03-30 20:52:59] app-docker.js not running. +[2025-03-30 20:53:01] app-docker.js not running. +[2025-03-30 20:53:03] app-docker.js not running. +[2025-03-30 20:53:05] app-docker.js not running. +[2025-03-30 20:53:07] app-docker.js not running. +[2025-03-30 20:53:09] app-docker.js not running. +[2025-03-30 20:53:11] app-docker.js not running. +[2025-03-30 20:53:13] app-docker.js not running. +[2025-03-30 20:53:15] app-docker.js not running. +[2025-03-30 20:53:18] app-docker.js not running. +[2025-03-30 20:53:20] app-docker.js not running. +[2025-03-30 20:53:22] app-docker.js not running. +[2025-03-30 20:53:24] app-docker.js not running. +[2025-03-30 20:53:26] app-docker.js not running. +[2025-03-30 20:53:28] app-docker.js not running. +[2025-03-30 20:53:30] app-docker.js not running. +[2025-03-30 20:53:32] app-docker.js not running. +[2025-03-30 20:53:34] app-docker.js not running. +[2025-03-30 20:53:36] app-docker.js not running. +[2025-03-30 20:53:38] app-docker.js not running. +[2025-03-30 20:53:40] app-docker.js not running. +[2025-03-30 20:53:42] app-docker.js not running. +[2025-03-30 20:53:44] app-docker.js not running. +[2025-03-30 20:53:46] app-docker.js not running. +[2025-03-30 20:53:48] app-docker.js not running. +[2025-03-30 20:53:50] app-docker.js not running. +[2025-03-30 20:53:52] app-docker.js not running. +[2025-03-30 20:53:54] app-docker.js not running. +[2025-03-30 20:53:56] app-docker.js not running. +[2025-03-30 20:53:58] app-docker.js not running. +[2025-03-30 20:54:00] app-docker.js not running. +[2025-03-30 20:54:02] app-docker.js not running. +[2025-03-30 20:54:04] app-docker.js not running. +[2025-03-30 20:54:06] app-docker.js not running. +[2025-03-30 20:54:08] app-docker.js not running. +[2025-03-30 20:54:10] app-docker.js not running. +[2025-03-30 20:54:12] app-docker.js not running. +[2025-03-30 20:54:14] app-docker.js not running. +[2025-03-30 20:54:16] app-docker.js not running. +[2025-03-30 20:54:18] app-docker.js not running. +[2025-03-30 20:54:20] app-docker.js not running. +[2025-03-30 20:54:23] app-docker.js not running. +[2025-03-30 20:54:25] app-docker.js not running. +[2025-03-30 20:54:27] app-docker.js not running. +[2025-03-30 20:54:29] app-docker.js not running. +[2025-03-30 20:54:31] app-docker.js not running. +[2025-03-30 20:54:33] app-docker.js not running. +[2025-03-30 20:54:35] app-docker.js not running. +[2025-03-30 20:54:37] app-docker.js not running. +[2025-03-30 20:54:39] app-docker.js not running. +[2025-03-30 20:54:41] app-docker.js not running. +[2025-03-30 20:54:43] app-docker.js not running. +[2025-03-30 20:54:45] app-docker.js not running. +[2025-03-30 20:54:47] app-docker.js not running. +[2025-03-30 20:54:49] app-docker.js not running. +[2025-03-30 20:54:51] app-docker.js not running. +[2025-03-30 20:54:53] app-docker.js not running. +[2025-03-30 20:54:55] app-docker.js not running. +[2025-03-30 20:54:57] app-docker.js not running. +[2025-03-30 20:54:59] app-docker.js not running. +[2025-03-30 20:55:01] app-docker.js not running. +[2025-03-30 20:55:03] app-docker.js not running. +[2025-03-30 20:55:05] app-docker.js not running. +[2025-03-30 20:55:07] app-docker.js not running. +[2025-03-30 20:55:09] app-docker.js not running. +[2025-03-30 20:55:11] app-docker.js not running. +[2025-03-30 20:55:13] app-docker.js not running. +[2025-03-30 20:55:15] app-docker.js not running. +[2025-03-30 20:55:17] app-docker.js not running. +[2025-03-30 20:55:19] app-docker.js not running. +[2025-03-30 20:55:21] app-docker.js not running. +[2025-03-30 20:55:23] app-docker.js not running. +[2025-03-30 20:55:25] app-docker.js not running. +[2025-03-30 20:55:27] app-docker.js not running. +[2025-03-30 20:55:30] app-docker.js not running. +[2025-03-30 20:55:32] app-docker.js not running. +[2025-03-30 20:55:34] app-docker.js not running. +[2025-03-30 20:55:36] app-docker.js not running. +[2025-03-30 20:55:38] app-docker.js not running. +[2025-03-30 20:55:40] app-docker.js not running. +[2025-03-30 20:55:42] app-docker.js not running. +[2025-03-30 20:55:44] app-docker.js not running. +[2025-03-30 20:55:46] app-docker.js not running. +[2025-03-30 20:55:48] app-docker.js not running. +[2025-03-30 20:55:50] app-docker.js not running. +[2025-03-30 20:55:52] app-docker.js not running. +[2025-03-30 20:55:54] app-docker.js not running. +[2025-03-30 20:55:56] app-docker.js not running. +[2025-03-30 20:55:58] app-docker.js not running. +[2025-03-30 20:56:00] app-docker.js not running. +[2025-03-30 20:56:02] app-docker.js not running. +[2025-03-30 20:56:04] app-docker.js not running. +[2025-03-30 20:56:06] app-docker.js not running. +[2025-03-30 20:56:08] app-docker.js not running. +[2025-03-30 20:56:10] app-docker.js not running. +[2025-03-30 20:56:12] app-docker.js not running. +[2025-03-30 20:56:14] app-docker.js not running. +[2025-03-30 20:56:16] app-docker.js not running. +[2025-03-30 20:56:18] app-docker.js not running. +[2025-03-30 20:56:20] app-docker.js not running. +[2025-03-30 20:56:22] app-docker.js not running. +[2025-03-30 20:56:24] app-docker.js not running. +[2025-03-30 20:56:26] app-docker.js not running. +[2025-03-30 20:56:28] app-docker.js not running. +[2025-03-30 20:56:30] app-docker.js not running. +[2025-03-30 20:56:32] app-docker.js not running. +[2025-03-30 20:56:34] app-docker.js not running. +[2025-03-30 20:56:36] app-docker.js not running. +[2025-03-30 20:56:38] app-docker.js not running. +[2025-03-30 20:56:41] app-docker.js not running. +[2025-03-30 20:56:43] app-docker.js not running. +[2025-03-30 20:56:45] app-docker.js not running. +[2025-03-30 20:56:47] app-docker.js not running. +[2025-03-30 20:56:49] app-docker.js not running. +[2025-03-30 20:56:51] app-docker.js not running. +[2025-03-30 20:56:53] app-docker.js not running. +[2025-03-30 20:56:55] app-docker.js not running. +[2025-03-30 20:56:57] app-docker.js not running. +[2025-03-30 20:56:59] app-docker.js not running. +[2025-03-30 20:57:01] app-docker.js not running. +[2025-03-30 20:57:03] app-docker.js not running. +[2025-03-30 20:57:05] app-docker.js not running. +[2025-03-30 20:57:07] app-docker.js not running. +[2025-03-30 20:57:09] app-docker.js not running. +[2025-03-30 20:57:11] app-docker.js not running. +[2025-03-30 20:57:13] app-docker.js not running. +[2025-03-30 20:57:15] app-docker.js not running. +[2025-03-30 20:57:17] app-docker.js not running. +[2025-03-30 20:57:19] app-docker.js not running. +[2025-03-30 20:57:21] app-docker.js not running. +[2025-03-30 20:57:23] app-docker.js not running. +[2025-03-30 20:57:25] app-docker.js not running. +[2025-03-30 20:57:27] app-docker.js not running. +[2025-03-30 20:57:29] app-docker.js not running. +[2025-03-30 20:57:31] app-docker.js not running. +[2025-03-30 20:57:34] app-docker.js not running. +[2025-03-30 20:57:36] app-docker.js not running. +[2025-03-30 20:57:38] app-docker.js not running. +[2025-03-30 20:57:40] app-docker.js not running. +[2025-03-30 20:57:42] app-docker.js not running. +[2025-03-30 20:57:44] app-docker.js not running. +[2025-03-30 20:57:46] app-docker.js not running. +[2025-03-30 20:57:48] app-docker.js not running. +[2025-03-30 20:57:50] app-docker.js not running. +[2025-03-30 20:57:52] app-docker.js not running. +[2025-03-30 20:57:54] app-docker.js not running. +[2025-03-30 20:57:56] app-docker.js not running. +[2025-03-30 20:57:58] app-docker.js not running. +[2025-03-30 20:58:00] app-docker.js not running. +[2025-03-30 20:58:02] app-docker.js not running. +[2025-03-30 20:58:04] app-docker.js not running. +[2025-03-30 20:58:06] app-docker.js not running. +[2025-03-30 20:58:08] app-docker.js not running. +[2025-03-30 20:58:10] app-docker.js not running. +[2025-03-30 20:58:13] app-docker.js not running. +[2025-03-30 20:58:15] app-docker.js not running. +[2025-03-30 20:58:17] app-docker.js not running. +[2025-03-30 20:58:19] app-docker.js not running. +[2025-03-30 20:58:21] app-docker.js not running. +[2025-03-30 20:58:23] app-docker.js not running. +[2025-03-30 20:58:25] app-docker.js not running. +[2025-03-30 20:58:27] app-docker.js not running. +[2025-03-30 20:58:29] app-docker.js not running. +[2025-03-30 20:58:31] app-docker.js not running. +[2025-03-30 20:58:33] app-docker.js not running. +[2025-03-30 20:58:35] app-docker.js not running. +[2025-03-30 20:58:37] app-docker.js not running. +[2025-03-30 20:58:39] app-docker.js not running. +[2025-03-30 20:58:41] app-docker.js not running. +[2025-03-30 20:58:43] app-docker.js not running. +[2025-03-30 20:58:45] app-docker.js not running. +[2025-03-30 20:58:47] app-docker.js not running. +[2025-03-30 20:58:49] app-docker.js not running. +[2025-03-30 20:58:51] app-docker.js not running. +[2025-03-30 20:58:53] app-docker.js not running. +[2025-03-30 20:58:55] app-docker.js not running. +[2025-03-30 20:58:57] app-docker.js not running. +[2025-03-30 20:58:59] app-docker.js not running. +[2025-03-30 20:59:01] app-docker.js not running. +[2025-03-30 20:59:03] app-docker.js not running. +[2025-03-30 20:59:05] app-docker.js not running. +[2025-03-30 20:59:07] app-docker.js not running. +[2025-03-30 20:59:09] app-docker.js not running. +[2025-03-30 20:59:11] app-docker.js not running. +[2025-03-30 20:59:13] app-docker.js not running. +[2025-03-30 20:59:15] app-docker.js not running. +[2025-03-30 20:59:17] app-docker.js not running. +[2025-03-30 20:59:19] app-docker.js not running. +[2025-03-30 20:59:22] app-docker.js not running. +[2025-03-30 20:59:24] app-docker.js not running. +[2025-03-30 20:59:26] app-docker.js not running. +[2025-03-30 20:59:28] app-docker.js not running. +[2025-03-30 20:59:30] app-docker.js not running. +[2025-03-30 20:59:32] app-docker.js not running. +[2025-03-30 20:59:34] app-docker.js not running. +[2025-03-30 20:59:36] app-docker.js not running. +[2025-03-30 20:59:38] app-docker.js not running. +[2025-03-30 20:59:40] app-docker.js not running. +[2025-03-30 20:59:42] app-docker.js not running. +[2025-03-30 20:59:44] app-docker.js not running. +[2025-03-30 20:59:46] app-docker.js not running. +[2025-03-30 20:59:48] app-docker.js not running. +[2025-03-30 20:59:50] app-docker.js not running. +[2025-03-30 20:59:52] app-docker.js not running. +[2025-03-30 20:59:54] app-docker.js not running. +[2025-03-30 20:59:56] app-docker.js not running. +[2025-03-30 20:59:58] app-docker.js not running. +[2025-03-30 21:00:00] app-docker.js not running. +[2025-03-30 21:00:02] app-docker.js not running. +[2025-03-30 21:00:04] app-docker.js not running. +[2025-03-30 21:00:06] app-docker.js not running. +[2025-03-30 21:00:08] app-docker.js not running. +[2025-03-30 21:00:10] app-docker.js not running. +[2025-03-30 21:00:12] app-docker.js not running. +[2025-03-30 21:00:14] app-docker.js not running. +[2025-03-30 21:00:16] app-docker.js not running. +[2025-03-30 21:00:18] app-docker.js not running. +[2025-03-30 21:00:20] app-docker.js not running. +[2025-03-30 21:00:22] app-docker.js not running. +[2025-03-30 21:00:24] app-docker.js not running. +[2025-03-30 21:00:26] app-docker.js not running. +[2025-03-30 21:00:28] app-docker.js not running. +[2025-03-30 21:00:30] app-docker.js not running. +[2025-03-30 21:00:32] app-docker.js not running. +[2025-03-30 21:00:35] app-docker.js not running. +[2025-03-30 21:00:37] app-docker.js not running. +[2025-03-30 21:00:39] app-docker.js not running. +[2025-03-30 21:00:41] app-docker.js not running. +[2025-03-30 21:00:43] app-docker.js not running. +[2025-03-30 21:00:45] app-docker.js not running. +[2025-03-30 21:00:47] app-docker.js not running. +[2025-03-30 21:00:49] app-docker.js not running. +[2025-03-30 21:00:51] app-docker.js not running. +[2025-03-30 21:00:53] app-docker.js not running. +[2025-03-30 21:00:55] app-docker.js not running. +[2025-03-30 21:00:57] app-docker.js not running. +[2025-03-30 21:00:59] app-docker.js not running. +[2025-03-30 21:01:01] app-docker.js not running. +[2025-03-30 21:01:03] app-docker.js not running. +[2025-03-30 21:01:05] app-docker.js not running. +[2025-03-30 21:01:07] app-docker.js not running. +[2025-03-30 21:01:09] app-docker.js not running. +[2025-03-30 21:01:11] app-docker.js not running. +[2025-03-30 21:01:13] app-docker.js not running. +[2025-03-30 21:01:15] app-docker.js not running. +[2025-03-30 21:01:17] app-docker.js not running. +[2025-03-30 21:01:19] app-docker.js not running. +[2025-03-30 21:01:21] app-docker.js not running. +[2025-03-30 21:01:23] app-docker.js not running. +[2025-03-30 21:01:25] app-docker.js not running. +[2025-03-30 21:01:27] app-docker.js not running. +[2025-03-30 21:01:29] app-docker.js not running. +[2025-03-30 21:01:31] app-docker.js not running. +[2025-03-30 21:01:33] app-docker.js not running. +[2025-03-30 21:01:35] app-docker.js not running. +[2025-03-30 21:01:37] app-docker.js not running. +[2025-03-30 21:01:39] app-docker.js not running. +[2025-03-30 21:01:41] app-docker.js not running. +[2025-03-30 21:01:43] app-docker.js not running. +[2025-03-30 21:01:46] app-docker.js not running. +[2025-03-30 21:01:48] app-docker.js not running. +[2025-03-30 21:01:50] app-docker.js not running. +[2025-03-30 21:01:52] app-docker.js not running. +[2025-03-30 21:01:54] app-docker.js not running. +[2025-03-30 21:01:56] app-docker.js not running. +[2025-03-30 21:01:58] app-docker.js not running. +[2025-03-30 21:02:00] app-docker.js not running. +[2025-03-30 21:02:02] app-docker.js not running. +[2025-03-30 21:02:04] app-docker.js not running. +[2025-03-30 21:02:06] app-docker.js not running. +[2025-03-30 21:02:08] app-docker.js not running. +[2025-03-30 21:02:10] app-docker.js not running. +[2025-03-30 21:02:12] app-docker.js not running. +[2025-03-30 21:02:14] app-docker.js not running. +[2025-03-30 21:02:16] app-docker.js not running. +[2025-03-30 21:02:18] app-docker.js not running. +[2025-03-30 21:02:20] app-docker.js not running. +[2025-03-30 21:02:22] app-docker.js not running. +[2025-03-30 21:02:24] app-docker.js not running. +[2025-03-30 21:02:26] app-docker.js not running. +[2025-03-30 21:02:28] app-docker.js not running. +[2025-03-30 21:02:30] app-docker.js not running. +[2025-03-30 21:02:32] app-docker.js not running. +[2025-03-30 21:02:34] app-docker.js not running. +[2025-03-30 21:02:36] app-docker.js not running. +[2025-03-30 21:02:38] app-docker.js not running. +[2025-03-30 21:02:40] app-docker.js not running. +[2025-03-30 21:02:42] app-docker.js not running. +[2025-03-30 21:02:44] app-docker.js not running. +[2025-03-30 21:02:46] app-docker.js not running. +[2025-03-30 21:02:48] app-docker.js not running. +[2025-03-30 21:02:50] app-docker.js not running. +[2025-03-30 21:02:52] app-docker.js not running. +[2025-03-30 21:02:55] app-docker.js not running. +[2025-03-30 21:02:57] app-docker.js not running. +[2025-03-30 21:02:59] app-docker.js not running. +[2025-03-30 21:03:01] app-docker.js not running. +[2025-03-30 21:03:03] app-docker.js not running. +[2025-03-30 21:03:05] app-docker.js not running. +[2025-03-30 21:03:07] app-docker.js not running. +[2025-03-30 21:03:09] app-docker.js not running. +[2025-03-30 21:03:11] app-docker.js not running. +[2025-03-30 21:03:13] app-docker.js not running. +[2025-03-30 21:03:15] app-docker.js not running. +[2025-03-30 21:03:17] app-docker.js not running. +[2025-03-30 21:03:19] app-docker.js not running. +[2025-03-30 21:03:21] app-docker.js not running. +[2025-03-30 21:03:23] app-docker.js not running. +[2025-03-30 21:03:25] app-docker.js not running. +[2025-03-30 21:03:27] app-docker.js not running. +[2025-03-30 21:03:29] app-docker.js not running. +[2025-03-30 21:03:31] app-docker.js not running. +[2025-03-30 21:03:33] app-docker.js not running. +[2025-03-30 21:03:35] app-docker.js not running. +[2025-03-30 21:03:37] app-docker.js not running. +[2025-03-30 21:03:39] app-docker.js not running. +[2025-03-30 21:03:41] app-docker.js not running. +[2025-03-30 21:03:43] app-docker.js not running. +[2025-03-30 21:03:45] app-docker.js not running. +[2025-03-30 21:03:47] app-docker.js not running. +[2025-03-30 21:03:49] app-docker.js not running. +[2025-03-30 21:03:51] app-docker.js not running. +[2025-03-30 21:03:53] app-docker.js not running. +[2025-03-30 21:03:55] app-docker.js not running. +[2025-03-30 21:03:57] app-docker.js not running. +[2025-03-30 21:03:59] app-docker.js not running. +[2025-03-30 21:04:01] app-docker.js not running. +[2025-03-30 21:04:03] app-docker.js not running. +[2025-03-30 21:04:05] app-docker.js not running. +[2025-03-30 21:04:08] app-docker.js not running. +[2025-03-30 21:04:10] app-docker.js not running. +[2025-03-30 21:04:12] app-docker.js not running. +[2025-03-30 21:04:14] app-docker.js not running. +[2025-03-30 21:04:16] app-docker.js not running. +[2025-03-30 21:04:18] app-docker.js not running. +[2025-03-30 21:04:20] app-docker.js not running. +[2025-03-30 21:04:22] app-docker.js not running. +[2025-03-30 21:04:24] app-docker.js not running. +[2025-03-30 21:04:26] app-docker.js not running. +[2025-03-30 21:04:28] app-docker.js not running. +[2025-03-30 21:04:30] app-docker.js not running. +[2025-03-30 21:04:32] app-docker.js not running. +[2025-03-30 21:04:34] app-docker.js not running. +[2025-03-30 21:04:36] app-docker.js not running. +[2025-03-30 21:04:38] app-docker.js not running. +[2025-03-30 21:04:40] app-docker.js not running. +[2025-03-30 21:04:42] app-docker.js not running. +[2025-03-30 21:04:44] app-docker.js not running. +[2025-03-30 21:04:46] app-docker.js not running. +[2025-03-30 21:04:48] app-docker.js not running. +[2025-03-30 21:04:50] app-docker.js not running. +[2025-03-30 21:04:52] app-docker.js not running. +[2025-03-30 21:04:54] app-docker.js not running. +[2025-03-30 21:04:56] app-docker.js not running. +[2025-03-30 21:04:58] app-docker.js not running. +[2025-03-30 21:05:00] app-docker.js not running. +[2025-03-30 21:05:02] app-docker.js not running. +[2025-03-30 21:05:04] app-docker.js not running. +[2025-03-30 21:05:06] app-docker.js not running. +[2025-03-30 21:05:08] app-docker.js not running. +[2025-03-30 21:05:10] app-docker.js not running. +[2025-03-30 21:05:12] app-docker.js not running. +[2025-03-30 21:05:14] app-docker.js not running. +[2025-03-30 21:05:16] app-docker.js not running. +[2025-03-30 21:05:19] app-docker.js not running. +[2025-03-30 21:05:21] app-docker.js not running. +[2025-03-30 21:05:23] app-docker.js not running. +[2025-03-30 21:05:25] app-docker.js not running. +[2025-03-30 21:05:27] app-docker.js not running. +[2025-03-30 21:05:29] app-docker.js not running. +[2025-03-30 21:05:31] app-docker.js not running. +[2025-03-30 21:05:33] app-docker.js not running. +[2025-03-30 21:05:35] app-docker.js not running. +[2025-03-30 21:05:37] app-docker.js not running. +[2025-03-30 21:05:39] app-docker.js not running. +[2025-03-30 21:05:41] app-docker.js not running. +[2025-03-30 21:05:43] app-docker.js not running. +[2025-03-30 21:05:45] app-docker.js not running. +[2025-03-30 21:05:47] app-docker.js not running. +[2025-03-30 21:05:49] app-docker.js not running. +[2025-03-30 21:05:51] app-docker.js not running. +[2025-03-30 21:05:53] app-docker.js not running. +[2025-03-30 21:05:55] app-docker.js not running. +[2025-03-30 21:05:57] app-docker.js not running. +[2025-03-30 21:05:59] app-docker.js not running. +[2025-03-30 21:06:01] app-docker.js not running. +[2025-03-30 21:06:03] app-docker.js not running. +[2025-03-30 21:06:05] app-docker.js not running. +[2025-03-30 21:06:07] app-docker.js not running. +[2025-03-30 21:06:09] app-docker.js not running. +[2025-03-30 21:06:11] app-docker.js not running. +[2025-03-30 21:06:13] app-docker.js not running. +[2025-03-30 21:06:15] app-docker.js not running. +[2025-03-30 21:06:17] app-docker.js not running. +[2025-03-30 21:06:19] app-docker.js not running. +[2025-03-30 21:06:21] app-docker.js not running. +[2025-03-30 21:06:23] app-docker.js not running. +[2025-03-30 21:06:25] app-docker.js not running. +[2025-03-30 21:06:28] app-docker.js not running. +[2025-03-30 21:06:30] app-docker.js not running. +[2025-03-30 21:06:32] app-docker.js not running. +[2025-03-30 21:06:34] app-docker.js not running. +[2025-03-30 21:06:36] app-docker.js not running. +[2025-03-30 21:06:38] app-docker.js not running. +[2025-03-30 21:06:40] app-docker.js not running. +[2025-03-30 21:06:42] app-docker.js not running. +[2025-03-30 21:06:44] app-docker.js not running. +[2025-03-30 21:06:46] app-docker.js not running. +[2025-03-30 21:06:48] app-docker.js not running. +[2025-03-30 21:06:50] app-docker.js not running. +[2025-03-30 21:06:52] app-docker.js not running. +[2025-03-30 21:06:54] app-docker.js not running. +[2025-03-30 21:06:56] app-docker.js not running. +[2025-03-30 21:06:58] app-docker.js not running. +[2025-03-30 21:07:00] app-docker.js not running. +[2025-03-30 21:07:02] app-docker.js not running. +[2025-03-30 21:07:04] app-docker.js not running. +[2025-03-30 21:07:06] app-docker.js not running. +[2025-03-30 21:07:08] app-docker.js not running. +[2025-03-30 21:07:10] app-docker.js not running. +[2025-03-30 21:07:12] app-docker.js not running. +[2025-03-30 21:07:14] app-docker.js not running. +[2025-03-30 21:07:16] app-docker.js not running. +[2025-03-30 21:07:18] app-docker.js not running. +[2025-03-30 21:07:20] app-docker.js not running. +[2025-03-30 21:07:22] app-docker.js not running. +[2025-03-30 21:07:24] app-docker.js not running. +[2025-03-30 21:07:26] app-docker.js not running. +[2025-03-30 21:07:28] app-docker.js not running. +[2025-03-30 21:07:30] app-docker.js not running. +[2025-03-30 21:07:32] app-docker.js not running. +[2025-03-30 21:07:34] app-docker.js not running. +[2025-03-30 21:07:37] app-docker.js not running. +[2025-03-30 21:07:39] app-docker.js not running. +[2025-03-30 21:07:41] app-docker.js not running. +[2025-03-30 21:07:43] app-docker.js not running. +[2025-03-30 21:07:45] app-docker.js not running. +[2025-03-30 21:07:47] app-docker.js not running. +[2025-03-30 21:07:49] app-docker.js not running. +[2025-03-30 21:07:51] app-docker.js not running. +[2025-03-30 21:07:53] app-docker.js not running. +[2025-03-30 21:07:55] app-docker.js not running. +[2025-03-30 21:07:57] app-docker.js not running. +[2025-03-30 21:07:59] app-docker.js not running. +[2025-03-30 21:08:01] app-docker.js not running. +[2025-03-30 21:08:03] app-docker.js not running. +[2025-03-30 21:08:05] app-docker.js not running. +[2025-03-30 21:08:07] app-docker.js not running. +[2025-03-30 21:08:09] app-docker.js not running. +[2025-03-30 21:08:11] app-docker.js not running. +[2025-03-30 21:08:13] app-docker.js not running. +[2025-03-30 21:08:15] app-docker.js not running. +[2025-03-30 21:08:17] app-docker.js not running. +[2025-03-30 21:08:19] app-docker.js not running. +[2025-03-30 21:08:21] app-docker.js not running. +[2025-03-30 21:08:23] app-docker.js not running. +[2025-03-30 21:08:25] app-docker.js not running. +[2025-03-30 21:08:27] app-docker.js not running. +[2025-03-30 21:08:29] app-docker.js not running. +[2025-03-30 21:08:31] app-docker.js not running. +[2025-03-30 21:08:33] app-docker.js not running. +[2025-03-30 21:08:35] app-docker.js not running. +[2025-03-30 21:08:37] app-docker.js not running. +[2025-03-30 21:08:39] app-docker.js not running. +[2025-03-30 21:08:41] app-docker.js not running. +[2025-03-30 21:08:44] app-docker.js not running. +[2025-03-30 21:08:46] app-docker.js not running. +[2025-03-30 21:08:48] app-docker.js not running. +[2025-03-30 21:08:50] app-docker.js not running. +[2025-03-30 21:08:52] app-docker.js not running. +[2025-03-30 21:08:54] app-docker.js not running. +[2025-03-30 21:08:56] app-docker.js not running. +[2025-03-30 21:08:58] app-docker.js not running. +[2025-03-30 21:09:00] app-docker.js not running. +[2025-03-30 21:09:02] app-docker.js not running. +[2025-03-30 21:09:04] app-docker.js not running. +[2025-03-30 21:09:06] app-docker.js not running. +[2025-03-30 21:09:08] app-docker.js not running. +[2025-03-30 21:09:10] app-docker.js not running. +[2025-03-30 21:09:12] app-docker.js not running. +[2025-03-30 21:09:14] app-docker.js not running. +[2025-03-30 21:09:16] app-docker.js not running. +[2025-03-30 21:09:18] app-docker.js not running. +[2025-03-30 21:09:20] app-docker.js not running. +[2025-03-30 21:09:22] app-docker.js not running. +[2025-03-30 21:09:24] app-docker.js not running. +[2025-03-30 21:09:26] app-docker.js not running. +[2025-03-30 21:09:28] app-docker.js not running. +[2025-03-30 21:09:30] app-docker.js not running. +[2025-03-30 21:09:32] app-docker.js not running. +[2025-03-30 21:09:34] app-docker.js not running. +[2025-03-30 21:09:36] app-docker.js not running. +[2025-03-30 21:09:38] app-docker.js not running. +[2025-03-30 21:09:40] app-docker.js not running. +[2025-03-30 21:09:42] app-docker.js not running. +[2025-03-30 21:09:44] app-docker.js not running. +[2025-03-30 21:09:46] app-docker.js not running. +[2025-03-30 21:09:48] app-docker.js not running. +[2025-03-30 21:09:50] app-docker.js not running. +[2025-03-30 21:09:52] app-docker.js not running. +[2025-03-30 21:09:55] app-docker.js not running. +[2025-03-30 21:09:57] app-docker.js not running. +[2025-03-30 21:09:59] app-docker.js not running. +[2025-03-30 21:10:01] app-docker.js not running. +[2025-03-30 21:10:03] app-docker.js not running. +[2025-03-30 21:10:05] app-docker.js not running. +[2025-03-30 21:10:07] app-docker.js not running. +[2025-03-30 21:10:09] app-docker.js not running. +[2025-03-30 21:10:11] app-docker.js not running. +[2025-03-30 21:10:13] app-docker.js not running. +[2025-03-30 21:10:15] app-docker.js not running. +[2025-03-30 21:10:17] app-docker.js not running. +[2025-03-30 21:10:19] app-docker.js not running. +[2025-03-30 21:10:21] app-docker.js not running. +[2025-03-30 21:10:23] app-docker.js not running. +[2025-03-30 21:10:25] app-docker.js not running. +[2025-03-30 21:10:27] app-docker.js not running. +[2025-03-30 21:10:29] app-docker.js not running. +[2025-03-30 21:10:31] app-docker.js not running. +[2025-03-30 21:10:33] app-docker.js not running. +[2025-03-30 21:10:35] app-docker.js not running. +[2025-03-30 21:10:37] app-docker.js not running. +[2025-03-30 21:10:39] app-docker.js not running. +[2025-03-30 21:10:41] app-docker.js not running. +[2025-03-30 21:10:43] app-docker.js not running. +[2025-03-30 21:10:45] app-docker.js not running. +[2025-03-30 21:10:47] app-docker.js not running. +[2025-03-30 21:10:49] app-docker.js not running. +[2025-03-30 21:10:51] app-docker.js not running. +[2025-03-30 21:10:53] app-docker.js not running. +[2025-03-30 21:10:55] app-docker.js not running. +[2025-03-30 21:10:57] app-docker.js not running. +[2025-03-30 21:10:59] app-docker.js not running. +[2025-03-30 21:11:01] app-docker.js not running. +[2025-03-30 21:11:04] app-docker.js not running. +[2025-03-30 21:11:06] app-docker.js not running. +[2025-03-30 21:11:08] app-docker.js not running. +[2025-03-30 21:11:10] app-docker.js not running. +[2025-03-30 21:11:12] app-docker.js not running. +[2025-03-30 21:11:14] app-docker.js not running. +[2025-03-30 21:11:16] app-docker.js not running. +[2025-03-30 21:11:18] app-docker.js not running. +[2025-03-30 21:11:20] app-docker.js not running. +[2025-03-30 21:11:22] app-docker.js not running. +[2025-03-30 21:11:24] app-docker.js not running. +[2025-03-30 21:11:26] app-docker.js not running. +[2025-03-30 21:11:28] app-docker.js not running. +[2025-03-30 21:11:30] app-docker.js not running. +[2025-03-30 21:11:32] app-docker.js not running. +[2025-03-30 21:11:34] app-docker.js not running. +[2025-03-30 21:11:36] app-docker.js not running. +[2025-03-30 21:11:38] app-docker.js not running. +[2025-03-30 21:11:40] app-docker.js not running. +[2025-03-30 21:11:42] app-docker.js not running. +[2025-03-30 21:11:44] app-docker.js not running. +[2025-03-30 21:11:46] app-docker.js not running. +[2025-03-30 21:11:48] app-docker.js not running. +[2025-03-30 21:11:50] app-docker.js not running. +[2025-03-30 21:11:52] app-docker.js not running. +[2025-03-30 21:11:54] app-docker.js not running. +[2025-03-30 21:11:56] app-docker.js not running. +[2025-03-30 21:11:58] app-docker.js not running. +[2025-03-30 21:12:00] app-docker.js not running. +[2025-03-30 21:12:02] app-docker.js not running. +[2025-03-30 21:12:04] app-docker.js not running. +[2025-03-30 21:12:06] app-docker.js not running. +[2025-03-30 21:12:08] app-docker.js not running. +[2025-03-30 21:12:10] app-docker.js not running. +[2025-03-30 21:12:12] app-docker.js not running. +[2025-03-30 21:12:14] app-docker.js not running. +[2025-03-30 21:12:17] app-docker.js not running. +[2025-03-30 21:12:19] app-docker.js not running. +[2025-03-30 21:12:21] app-docker.js not running. +[2025-03-30 21:12:23] app-docker.js not running. +[2025-03-30 21:12:25] app-docker.js not running. +[2025-03-30 21:12:27] app-docker.js not running. +[2025-03-30 21:12:29] app-docker.js not running. +[2025-03-30 21:12:31] app-docker.js not running. +[2025-03-30 21:12:33] app-docker.js not running. +[2025-03-30 21:12:35] app-docker.js not running. +[2025-03-30 21:12:37] app-docker.js not running. +[2025-03-30 21:12:39] app-docker.js not running. +[2025-03-30 21:12:41] app-docker.js not running. +[2025-03-30 21:12:43] app-docker.js not running. +[2025-03-30 21:12:45] app-docker.js not running. +[2025-03-30 21:12:47] app-docker.js not running. +[2025-03-30 21:12:49] app-docker.js not running. +[2025-03-30 21:12:51] app-docker.js not running. +[2025-03-30 21:12:53] app-docker.js not running. +[2025-03-30 21:12:55] app-docker.js not running. +[2025-03-30 21:12:57] app-docker.js not running. +[2025-03-30 21:12:59] app-docker.js not running. +[2025-03-30 21:13:01] app-docker.js not running. +[2025-03-30 21:13:03] app-docker.js not running. +[2025-03-30 21:13:05] app-docker.js not running. +[2025-03-30 21:13:07] app-docker.js not running. +[2025-03-30 21:13:09] app-docker.js not running. +[2025-03-30 21:13:11] app-docker.js not running. +[2025-03-30 21:13:13] app-docker.js not running. +[2025-03-30 21:13:15] app-docker.js not running. +[2025-03-30 21:13:17] app-docker.js not running. +[2025-03-30 21:13:19] app-docker.js not running. +[2025-03-30 21:13:21] app-docker.js not running. +[2025-03-30 21:13:23] app-docker.js not running. +[2025-03-30 21:13:25] app-docker.js not running. +[2025-03-30 21:13:27] app-docker.js not running. +[2025-03-30 21:13:30] app-docker.js not running. +[2025-03-30 21:13:32] app-docker.js not running. +[2025-03-30 21:13:34] app-docker.js not running. +[2025-03-30 21:13:36] app-docker.js not running. +[2025-03-30 21:13:38] app-docker.js not running. +[2025-03-30 21:13:40] app-docker.js not running. +[2025-03-30 21:13:42] app-docker.js not running. +[2025-03-30 21:13:44] app-docker.js not running. +[2025-03-30 21:13:46] app-docker.js not running. +[2025-03-30 21:13:48] app-docker.js not running. +[2025-03-30 21:13:50] app-docker.js not running. +[2025-03-30 21:13:52] app-docker.js not running. +[2025-03-30 21:13:54] app-docker.js not running. +[2025-03-30 21:13:56] app-docker.js not running. +[2025-03-30 21:13:58] app-docker.js not running. +[2025-03-30 21:14:00] app-docker.js not running. +[2025-03-30 21:14:02] app-docker.js not running. +[2025-03-30 21:14:04] app-docker.js not running. +[2025-03-30 21:14:06] app-docker.js not running. +[2025-03-30 21:14:08] app-docker.js not running. +[2025-03-30 21:14:10] app-docker.js not running. +[2025-03-30 21:14:12] app-docker.js not running. +[2025-03-30 21:14:14] app-docker.js not running. +[2025-03-30 21:14:16] app-docker.js not running. +[2025-03-30 21:14:18] app-docker.js not running. +[2025-03-30 21:14:20] app-docker.js not running. +[2025-03-30 21:14:22] app-docker.js not running. +[2025-03-30 21:14:24] app-docker.js not running. +[2025-03-30 21:14:26] app-docker.js not running. +[2025-03-30 21:14:28] app-docker.js not running. +[2025-03-30 21:14:30] app-docker.js not running. +[2025-03-30 21:14:32] app-docker.js not running. +[2025-03-30 21:14:34] app-docker.js not running. +[2025-03-30 21:14:36] app-docker.js not running. +[2025-03-30 21:14:38] app-docker.js not running. +[2025-03-30 21:14:40] app-docker.js not running. +[2025-03-30 21:14:43] app-docker.js not running. +[2025-03-30 21:14:45] app-docker.js not running. +[2025-03-30 21:14:47] app-docker.js not running. +[2025-03-30 21:14:49] app-docker.js not running. +[2025-03-30 21:14:51] app-docker.js not running. +[2025-03-30 21:14:53] app-docker.js not running. +[2025-03-30 21:14:55] app-docker.js not running. +[2025-03-30 21:14:57] app-docker.js not running. +[2025-03-30 21:14:59] app-docker.js not running. +[2025-03-30 21:15:01] app-docker.js not running. +[2025-03-30 21:15:03] app-docker.js not running. +[2025-03-30 21:15:05] app-docker.js not running. +[2025-03-30 21:15:07] app-docker.js not running. +[2025-03-30 21:15:09] app-docker.js not running. +[2025-03-30 21:15:11] app-docker.js not running. +[2025-03-30 21:15:13] app-docker.js not running. +[2025-03-30 21:15:15] app-docker.js not running. +[2025-03-30 21:15:17] app-docker.js not running. +[2025-03-30 21:15:19] app-docker.js not running. +[2025-03-30 21:15:21] app-docker.js not running. +[2025-03-30 21:15:23] app-docker.js not running. +[2025-03-30 21:15:25] app-docker.js not running. +[2025-03-30 21:15:27] app-docker.js not running. +[2025-03-30 21:15:29] app-docker.js not running. +[2025-03-30 21:15:31] app-docker.js not running. +[2025-03-30 21:15:33] app-docker.js not running. +[2025-03-30 21:15:35] app-docker.js not running. +[2025-03-30 21:15:37] app-docker.js not running. +[2025-03-30 21:15:39] app-docker.js not running. +[2025-03-30 21:15:41] app-docker.js not running. +[2025-03-30 21:15:43] app-docker.js not running. +[2025-03-30 21:15:45] app-docker.js not running. +[2025-03-30 21:15:47] app-docker.js not running. +[2025-03-30 21:15:49] app-docker.js not running. +[2025-03-30 21:15:52] app-docker.js not running. +[2025-03-30 21:15:54] app-docker.js not running. +[2025-03-30 21:15:56] app-docker.js not running. +[2025-03-30 21:15:58] app-docker.js not running. +[2025-03-30 21:16:00] app-docker.js not running. +[2025-03-30 21:16:02] app-docker.js not running. +[2025-03-30 21:16:04] app-docker.js not running. +[2025-03-30 21:16:06] app-docker.js not running. +[2025-03-30 21:16:08] app-docker.js not running. +[2025-03-30 21:16:10] app-docker.js not running. +[2025-03-30 21:16:12] app-docker.js not running. +[2025-03-30 21:16:14] app-docker.js not running. +[2025-03-30 21:16:16] app-docker.js not running. +[2025-03-30 21:16:18] app-docker.js not running. +[2025-03-30 21:16:20] app-docker.js not running. +[2025-03-30 21:16:22] app-docker.js not running. +[2025-03-30 21:16:24] app-docker.js not running. +[2025-03-30 21:16:26] app-docker.js not running. +[2025-03-30 21:16:28] app-docker.js not running. +[2025-03-30 21:16:30] app-docker.js not running. +[2025-03-30 21:16:32] app-docker.js not running. +[2025-03-30 21:16:34] app-docker.js not running. +[2025-03-30 21:16:36] app-docker.js not running. +[2025-03-30 21:16:38] app-docker.js not running. +[2025-03-30 21:16:40] app-docker.js not running. +[2025-03-30 21:16:42] app-docker.js not running. +[2025-03-30 21:16:44] app-docker.js not running. +[2025-03-30 21:16:46] app-docker.js not running. +[2025-03-30 21:16:48] app-docker.js not running. +[2025-03-30 21:16:50] app-docker.js not running. +[2025-03-30 21:16:52] app-docker.js not running. +[2025-03-30 21:16:54] app-docker.js not running. +[2025-03-30 21:16:56] app-docker.js not running. +[2025-03-30 21:16:58] app-docker.js not running. +[2025-03-30 21:17:00] app-docker.js not running. +[2025-03-30 21:17:02] app-docker.js not running. +[2025-03-30 21:17:04] app-docker.js not running. +[2025-03-30 21:17:07] app-docker.js not running. +[2025-03-30 21:17:09] app-docker.js not running. +[2025-03-30 21:17:11] app-docker.js not running. +[2025-03-30 21:17:13] app-docker.js not running. +[2025-03-30 21:17:15] app-docker.js not running. +[2025-03-30 21:17:17] app-docker.js not running. +[2025-03-30 21:17:19] app-docker.js not running. +[2025-03-30 21:17:21] app-docker.js not running. +[2025-03-30 21:17:23] app-docker.js not running. +[2025-03-30 21:17:25] app-docker.js not running. +[2025-03-30 21:17:27] app-docker.js not running. +[2025-03-30 21:17:29] app-docker.js not running. +[2025-03-30 21:17:31] app-docker.js not running. +[2025-03-30 21:17:33] app-docker.js not running. +[2025-03-30 21:17:35] app-docker.js not running. +[2025-03-30 21:17:37] app-docker.js not running. +[2025-03-30 21:17:39] app-docker.js not running. +[2025-03-30 21:17:41] app-docker.js not running. +[2025-03-30 21:17:43] app-docker.js not running. +[2025-03-30 21:17:45] app-docker.js not running. +[2025-03-30 21:17:47] app-docker.js not running. +[2025-03-30 21:17:49] app-docker.js not running. +[2025-03-30 21:17:51] app-docker.js not running. +[2025-03-30 21:17:53] app-docker.js not running. +[2025-03-30 21:17:55] app-docker.js not running. +[2025-03-30 21:17:57] app-docker.js not running. +[2025-03-30 21:17:59] app-docker.js not running. +[2025-03-30 21:18:01] app-docker.js not running. +[2025-03-30 21:18:03] app-docker.js not running. +[2025-03-30 21:18:05] app-docker.js not running. +[2025-03-30 21:18:07] app-docker.js not running. +[2025-03-30 21:18:09] app-docker.js not running. +[2025-03-30 21:18:11] app-docker.js not running. +[2025-03-30 21:18:13] app-docker.js not running. +[2025-03-30 21:18:15] app-docker.js not running. +[2025-03-30 21:18:17] app-docker.js not running. +[2025-03-30 21:18:20] app-docker.js not running. +[2025-03-30 21:18:22] app-docker.js not running. +[2025-03-30 21:18:24] app-docker.js not running. +[2025-03-30 21:18:26] app-docker.js not running. +[2025-03-30 21:18:28] app-docker.js not running. +[2025-03-30 21:18:30] app-docker.js not running. +[2025-03-30 21:18:32] app-docker.js not running. +[2025-03-30 21:18:34] app-docker.js not running. +[2025-03-30 21:18:36] app-docker.js not running. +[2025-03-30 21:18:38] app-docker.js not running. +[2025-03-30 21:18:40] app-docker.js not running. +[2025-03-30 21:18:42] app-docker.js not running. +[2025-03-30 21:18:44] app-docker.js not running. +[2025-03-30 21:18:46] app-docker.js not running. +[2025-03-30 21:18:48] app-docker.js not running. +[2025-03-30 21:18:50] app-docker.js not running. +[2025-03-30 21:18:52] app-docker.js not running. +[2025-03-30 21:18:54] app-docker.js not running. +[2025-03-30 21:18:56] app-docker.js not running. +[2025-03-30 21:18:58] app-docker.js not running. +[2025-03-30 21:19:00] app-docker.js not running. +[2025-03-30 21:19:02] app-docker.js not running. +[2025-03-30 21:19:04] app-docker.js not running. +[2025-03-30 21:19:06] app-docker.js not running. +[2025-03-30 21:19:08] app-docker.js not running. +[2025-03-30 21:19:10] app-docker.js not running. +[2025-03-30 21:19:12] app-docker.js not running. +[2025-03-30 21:19:14] app-docker.js not running. +[2025-03-30 21:19:16] app-docker.js not running. +[2025-03-30 21:19:18] app-docker.js not running. +[2025-03-30 21:19:20] app-docker.js not running. +[2025-03-30 21:19:22] app-docker.js not running. +[2025-03-30 21:19:24] app-docker.js not running. +[2025-03-30 21:19:26] app-docker.js not running. +[2025-03-30 21:19:28] app-docker.js not running. +[2025-03-30 21:19:31] app-docker.js not running. +[2025-03-30 21:19:33] app-docker.js not running. +[2025-03-30 21:19:35] app-docker.js not running. +[2025-03-30 21:19:37] app-docker.js not running. +[2025-03-30 21:19:39] app-docker.js not running. +[2025-03-30 21:19:41] app-docker.js not running. +[2025-03-30 21:19:43] app-docker.js not running. +[2025-03-30 21:19:45] app-docker.js not running. +[2025-03-30 21:19:47] app-docker.js not running. +[2025-03-30 21:19:49] app-docker.js not running. +[2025-03-30 21:19:51] app-docker.js not running. +[2025-03-30 21:19:53] app-docker.js not running. +[2025-03-30 21:19:55] app-docker.js not running. +[2025-03-30 21:19:57] app-docker.js not running. +[2025-03-30 21:19:59] app-docker.js not running. +[2025-03-30 21:20:01] app-docker.js not running. +[2025-03-30 21:20:03] app-docker.js not running. +[2025-03-30 21:20:05] app-docker.js not running. +[2025-03-30 21:20:07] app-docker.js not running. +[2025-03-30 21:20:09] app-docker.js not running. +[2025-03-30 21:20:11] app-docker.js not running. +[2025-03-30 21:20:13] app-docker.js not running. +[2025-03-30 21:20:15] app-docker.js not running. +[2025-03-30 21:20:17] app-docker.js not running. +[2025-03-30 21:20:19] app-docker.js not running. +[2025-03-30 21:20:21] app-docker.js not running. +[2025-03-30 21:20:23] app-docker.js not running. +[2025-03-30 21:20:25] app-docker.js not running. +[2025-03-30 21:20:27] app-docker.js not running. +[2025-03-30 21:20:29] app-docker.js not running. +[2025-03-30 21:20:31] app-docker.js not running. +[2025-03-30 21:20:33] app-docker.js not running. +[2025-03-30 21:20:35] app-docker.js not running. +[2025-03-30 21:20:37] app-docker.js not running. +[2025-03-30 21:20:39] app-docker.js not running. +[2025-03-30 21:20:41] app-docker.js not running. +[2025-03-30 21:20:44] app-docker.js not running. +[2025-03-30 21:20:46] app-docker.js not running. +[2025-03-30 21:20:48] app-docker.js not running. +[2025-03-30 21:20:50] app-docker.js not running. +[2025-03-30 21:20:52] app-docker.js not running. +[2025-03-30 21:20:54] app-docker.js not running. +[2025-03-30 21:20:56] app-docker.js not running. +[2025-03-30 21:20:58] app-docker.js not running. +[2025-03-30 21:21:00] app-docker.js not running. +[2025-03-30 21:21:02] app-docker.js not running. +[2025-03-30 21:21:04] app-docker.js not running. +[2025-03-30 21:21:06] app-docker.js not running. +[2025-03-30 21:21:08] app-docker.js not running. +[2025-03-30 21:21:10] app-docker.js not running. +[2025-03-30 21:21:12] app-docker.js not running. +[2025-03-30 21:21:14] app-docker.js not running. +[2025-03-30 21:21:16] app-docker.js not running. diff --git a/tools/serverkill-playbook.yml b/tools/serverkill-playbook.yml new file mode 100644 index 00000000..5dfe05dd --- /dev/null +++ b/tools/serverkill-playbook.yml @@ -0,0 +1,22 @@ +- name: Kill JAMScript Server on Port 3000 + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Kill server process running on port 3000 and log result + shell: | + { + PID=$(lsof -ti:3000) + if [ -n "$PID" ]; then + kill -9 $PID + echo "$(date) - Killed server on port 3000 (PID $PID)" + else + echo "$(date) - No server process found on port 3000" + fi + } > serverkill.log 2>&1 + args: + chdir: /home/jamtools/JAMScript/tools diff --git a/tools/serverrun-playbook.yml b/tools/serverrun-playbook.yml new file mode 100644 index 00000000..7cd50a17 --- /dev/null +++ b/tools/serverrun-playbook.yml @@ -0,0 +1,22 @@ +- name: Start JAMScript Tools Server + hosts: "{{ server }}" + gather_facts: no + tasks: + - name: Ensure the working directory is correct + shell: pwd + args: + chdir: /home/jamtools/JAMScript/tools + + - name: Start the server (Express API) in the background + shell: nohup node app-docker.js > server.log 2>&1 & + args: + chdir: /home/jamtools/JAMScript/tools + async: 10 + poll: 0 + + - name: Wait until the server port is open + wait_for: + host: "{{ ansible_host }}" + port: 3000 + delay: 3 + timeout: 30 diff --git a/tools/setup_jamscript.yml b/tools/setup_jamscript.yml new file mode 100644 index 00000000..c19857ce --- /dev/null +++ b/tools/setup_jamscript.yml @@ -0,0 +1,119 @@ +--- +- name: Setup JAMScript tools and run Node.js server + hosts: all + become: true + tasks: + # Update and install basic dependencies + - name: Update and upgrade the system + apt: + update_cache: yes + upgrade: dist + cache_valid_time: 3600 + + - name: Install basic dependencies + apt: + name: + - build-essential + - curl + - git + - wget + - unzip + - python3 + - python3-pip + state: present + + # Install Docker + - name: Install Docker + apt: + name: + - docker.io + state: present + + - name: Enable and start Docker service + service: + name: docker + enabled: yes + state: started + + - name: Add user to the Docker group + user: + name: "{{ ansible_user }}" + groups: docker + append: yes + + # Install Node.js and npm + - name: Add NodeSource repository + shell: curl -fsSL https://deb.nodesource.com/setup_18.x | bash - + args: + executable: /bin/bash + + - name: Install Node.js + apt: + name: nodejs + state: present + + - name: Verify Node.js and npm installation + shell: | + node -v + npm -v + + # Install zx for script execution + - name: Install zx globally + npm: + name: zx + global: yes + + # Install Mosquitto MQTT Broker + - name: Install Mosquitto MQTT Broker + apt: + name: + - mosquitto + - mosquitto-clients + state: present + + - name: Enable and start Mosquitto service + service: + name: mosquitto + enabled: yes + state: started + + # Clone the JAMScript repository + - name: Clone JAMScript repository + git: + repo: https://github.com/JeanKa25/JAMScript.git + dest: /root/JAMScript + version: ansible-setup + recursive: no + + # Run install.sh script + - name: Run install.sh script + shell: sudo ./install.sh + args: + chdir: /root/JAMScript + + # Run npm install + - name: Run npm install + npm: + path: /root/JAMScript + state: present + + # Ensure permissions for required files + - name: Ensure all .mjs files have execute permissions + file: + path: /root/JAMScript/tools + recurse: yes + state: directory + mode: '0755' + + - name: Ensure jt1.jxe has execute permissions + file: + path: /root/JAMScript/tools/jt1.jxe + state: file + mode: '0755' + + # Start the Node.js server using node + - name: Start the Node.js server in the background + shell: nohup node /root/JAMScript/tools/app.js > /root/JAMScript/server.log 2>&1 & + args: + executable: /bin/bash + diff --git a/tools/wrapper.mjs b/tools/wrapper.mjs new file mode 100755 index 00000000..13fc518f --- /dev/null +++ b/tools/wrapper.mjs @@ -0,0 +1,602 @@ +#!/usr/bin/env zx + +import commandLineArgs from 'command-line-args'; +import fetch from "node-fetch"; +import {getBatchArgs} from './parser.mjs'; + +//Define default server IP +let serverIP = "10.140.16.105"; + +// Read SSH key from client +const sshPublicKey = fs.readFileSync('/home/jamtools/.ssh/id_rsa.pub', 'utf8').trim(); + +// Get the command-line arguments +const endpointArgs = process.argv.slice(3); + +// Check if a custom server IP is provided via --serverIP= +const serverArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--serverIP=")); +if (serverArgIndex !== -1) { + serverIP = endpointArgs[serverArgIndex].split("=")[1]; + console.log(serverIP) + // Remove the serverIP argument so it doesn't interfere with other processing + endpointArgs.splice(serverArgIndex, 1); +} + + +// ex: zx wrapper.mjs jamrun jt1.jxe --app="DEMO" +// Validate and process the arguments +if (endpointArgs[0] === "jamrun") { + const fileName = endpointArgs[1]; + + //Index of parameters without value + const fogArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--fog")); + const cloudArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--cloud")); + const deviceArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--device")); + const bgArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--bg")); + const oldArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--old")); + const logArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--log")); + const verbArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--verb")); + const valgrindArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--valgrind")); + const localArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--local")); + + + // Index of parameters with value + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app=")); + const numArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--num=")); + const dataArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--data=")); + const tagsArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--tags=")); + const locArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--loc=")); + const edgeArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--edge=")); + const remoteArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--remote=")); + + + if (!fileName || appArgIndex === -1) { + console.error( + "Error: Missing required arguments. Usage: zx wrapper.mjs jamrun --app=" + ); + process.exit(1); + } + + // Extract mandatory argument + const appName = endpointArgs[appArgIndex].split("=")[1]; // Extract app name + + let numName, dataName, tagsName, locName, edgeName, remoteName, fogName, cloudName, deviceName, bgName,oldName, logName, verbName, valgrindName, localName ; + + // Extract arguments with value if present + if(numArgIndex != -1) {numName = endpointArgs[numArgIndex].split("=")[1];} // Extract num name + if(dataArgIndex != -1) {dataName = endpointArgs[dataArgIndex].split("=")[1];} // Extract data name + if(tagsArgIndex != -1) {tagsName = endpointArgs[tagsArgIndex].split("=")[1];} // Extract tag name + if(locArgIndex != -1) {locName = endpointArgs[locArgIndex].split("=")[1];} // Extract loc name + if(edgeArgIndex != -1) {edgeName = endpointArgs[edgeArgIndex].split("=")[1];} // Extract edge name + if(remoteArgIndex != -1) {remoteName = endpointArgs[remoteArgIndex].split("=")[1];} // Extract remote name + + + // Use arguments without value if present + if(fogArgIndex != -1) {fogName = "fog"}; //fog + if(cloudArgIndex != -1) {cloudName = "cloud"}; //cloud + if(deviceArgIndex != -1) {deviceName = "device"}; //device + if(bgArgIndex != -1) {bgName = "bg"}; //bg + if(oldArgIndex != -1) {oldName = "old"}; //old + if(logArgIndex != -1) {logName = "log"}; //log + if(verbArgIndex != -1) {verbName = "verb"}; //verb + if(valgrindArgIndex != -1) {valgrindName = "valgrind"}; //valgrind + if(localArgIndex != -1) {localName = "local"}; //local + + // Construct the JSON payload + const payload = { + file: fileName, + app_name: appName, + }; + + // Add the relevent non mandatory arguments for the payload + if (numName) payload.num = numName; + if (dataName) payload.data = dataName; + if (tagsName) payload.tags = tagsName; + if (locName) payload.loc = locName; + if (edgeName) payload.edge = edgeName; + if (remoteName) payload.remote = remoteName; + + if (fogName) payload.fog = fogName; + if (cloudName) payload.cloud = cloudName; + if (deviceName) payload.device = deviceName; + if (bgName) payload.bg = bgName; + if (oldName) payload.old = oldName; + if (logName) payload.log = logName; + if (verbName) payload.verb = verbName; + if (valgrindName) payload.valgrind = valgrindName; + if (localName) payload.local = locName; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamrun`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +} + + +// ex: zx wrapper.mjs jambatch jt1.jxe ... +// Validate and process the arguments. jambatch is just a collection of jamrun +if (endpointArgs[0] === "jambatch") { + + + let argsBatchParsed = getBatchArgs(endpointArgs.slice(1)); + + // For each batch + for(let i = 0; i < argsBatchParsed.length - 1; i++) + { + let setArgs = argsBatchParsed[i]; + + const fileName = setArgs[0]; + + //Index of parameters without value + const fogArgIndex = setArgs.findIndex((arg) => arg.startsWith("--fog")); + const cloudArgIndex = setArgs.findIndex((arg) => arg.startsWith("--cloud")); + const deviceArgIndex = setArgs.findIndex((arg) => arg.startsWith("--device")); + const bgArgIndex = setArgs.findIndex((arg) => arg.startsWith("--bg")); + const oldArgIndex = setArgs.findIndex((arg) => arg.startsWith("--old")); + const logArgIndex = setArgs.findIndex((arg) => arg.startsWith("--log")); + const verbArgIndex = setArgs.findIndex((arg) => arg.startsWith("--verb")); + const valgrindArgIndex = setArgs.findIndex((arg) => arg.startsWith("--valgrind")); + const localArgIndex = setArgs.findIndex((arg) => arg.startsWith("--local")); + + + // Index of parameters with value + const appArgIndex = setArgs.findIndex((arg) => arg.startsWith("--app=")); + const numArgIndex = setArgs.findIndex((arg) => arg.startsWith("--num=")); + const dataArgIndex = setArgs.findIndex((arg) => arg.startsWith("--data=")); + const tagsArgIndex = setArgs.findIndex((arg) => arg.startsWith("--tags=")); + const locArgIndex = setArgs.findIndex((arg) => arg.startsWith("--loc=")); + const edgeArgIndex = setArgs.findIndex((arg) => arg.startsWith("--edge=")); + const remoteArgIndex = setArgs.findIndex((arg) => arg.startsWith("--remote=")); + + + let appName, numName, dataName, tagsName, locName, edgeName, remoteName, fogName, cloudName, deviceName, bgName,oldName, logName, verbName, valgrindName, localName ; + + // Extract arguments with value if present + if(appArgIndex != -1) {appName = setArgs[appArgIndex].split("=")[1];} // Extract app name + if(numArgIndex != -1) {numName = setArgs[numArgIndex].split("=")[1];} // Extract num name + if(dataArgIndex != -1) {dataName = setArgs[dataArgIndex].split("=")[1];} // Extract data name + if(tagsArgIndex != -1) {tagsName = setArgs[tagsArgIndex].split("=")[1];} // Extract tag name + if(locArgIndex != -1) {locName = setArgs[locArgIndex].split("=")[1];} // Extract loc name + if(edgeArgIndex != -1) {edgeName = setArgs[edgeArgIndex].split("=")[1];} // Extract edge name + if(remoteArgIndex != -1) {remoteName = setArgs[remoteArgIndex].split("=")[1];} // Extract remote name + + + // Use arguments without value if present + if(fogArgIndex != -1) {fogName = "fog"}; //fog + if(cloudArgIndex != -1) {cloudName = "cloud"}; //cloud + if(deviceArgIndex != -1) {deviceName = "device"}; //device + if(bgArgIndex != -1) {bgName = "bg"}; //bg + if(oldArgIndex != -1) {oldName = "old"}; //old + if(logArgIndex != -1) {logName = "log"}; //log + if(verbArgIndex != -1) {verbName = "verb"}; //verb + if(valgrindArgIndex != -1) {valgrindName = "valgrind"}; //valgrind + if(localArgIndex != -1) {localName = "local"}; //local + + // Construct the JSON payload + const payload = { + file: fileName, + app_name: appName + }; + + // Add to payload if necessary + if (numName) payload.num = numName; + if (dataName) payload.data = dataName; + if (tagsName) payload.tags = tagsName; + if (locName) payload.loc = locName; + if (edgeName) payload.edge = edgeName; + if (remoteName) payload.remote = remoteName; + + if (fogName) payload.fog = fogName; + if (cloudName) payload.cloud = cloudName; + if (deviceName) payload.device = deviceName; + if (bgName) payload.bg = bgName; + if (oldName) payload.old = oldName; + if (logName) payload.log = logName; + if (verbName) payload.verb = verbName; + if (valgrindName) payload.valgrind = valgrindName; + if (localName) payload.local = locName; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamrun`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); + } +} + + +// ex: zx wrapper.mjs jamlog --program=jt1.jxe --app="DEMO" --port=1883 +// Validate and process the arguments +if (endpointArgs[0] === "jamlog") { + // Get index of parameters + const programArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--program=")); + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app=")); + const portArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--port=")); + + const remoteArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--remote=")); + const tailArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--tail=")); + const cArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--c")); + const jArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--j")); + + + if (programArgIndex === -1 || appArgIndex === -1 || portArgIndex === -1) { + console.error( + "Error: Missing required arguments. Usage: zx wrapper.mjs jamlog --program= --app= --port=" + ); + process.exit(1); + } + + let programName, appName, portName, remoteName, tailName, cName, jName; + + // If the parameter is present, extract the relevent information + programName = endpointArgs[programArgIndex].split("=")[1]; // Extract program name + appName = endpointArgs[appArgIndex].split("=")[1]; // Extract app name + portName = endpointArgs[portArgIndex].split("=")[1]; // Extract port name + if (remoteArgIndex != -1) {remoteName = endpointArgs[remoteArgIndex].split("=")[1];} // Extract remote name + if (tailArgIndex != -1) {tailName = endpointArgs[tailArgIndex].split("=")[1];} // Extract tail name + + if(cArgIndex != -1) {cName = "c"}; //c + if(jArgIndex != -1) {jName = "j"}; //j + + + // Construct the JSON payload + const payload = { + program: programName, + app: appName, + port: portName + }; + + // Add the non-mandatory parameters needed for the endpoint + if (remoteName) payload.remote = remoteName; + if (tailName) payload.tail = tailName; + if (cName) payload.c = cName; + if (jName) payload.j = jName; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamlog`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +} + +// ex: zx wrapper.mjs jamlist +// Validate and process the arguments +if (endpointArgs[0] === "jamlist") { + + //Get parameters without value associated with it + const helpArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--help")); + const allArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--all")); + const monitorArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--monitor")); + + // Get index of parameters with a value associated with it + const typeArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--type==")); + const dataStoreArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--dataStore==")); + const tmuxidIndex = endpointArgs.findIndex((arg) => arg.startsWith("--tmuxid==")); + const portArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--port==")); + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app==")); + const progArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--prog==")); + const remomteArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--remote==")); + + let helpName, allName, monitorName, typeName,dataStoreName,tmuxName, portName, appName, programName, remoteName; + + // Use non-argument if present + if(helpArgIndex != -1) {helpName = "help"}; //Help + if(allArgIndex != -1) {allName = "all"}; //All + if(monitorArgIndex != -1) {monitorName = "monitor"}; //Monitor + + // If the parameter with value is present, extract the value + if (typeArgIndex != -1) {typeName = endpointArgs[typeArgIndex].split("==")[1];} // Extract type + if (dataStoreArgIndex != -1) {dataStoreName = endpointArgs[dataStoreArgIndex].split("==")[1];} // Extract dataStore + if (tmuxidIndex != -1) {tmuxName = endpointArgs[tmuxidIndex].split("==")[1];} // Extract tmux + if (portArgIndex != -1) {portName = endpointArgs[portArgIndex].split("==")[1];} // Extract port + if (appArgIndex != -1) {appName = endpointArgs[appArgIndex].split("==")[1];} // Extract app + if (progArgIndex != -1) {programName = endpointArgs[progArgIndex].split("==")[1];} // Extract prog + if (remomteArgIndex != -1) {remoteName = endpointArgs[remomteArgIndex].split("==")[1];} // Extract remote + + // Construct the JSON payload + let payload = { + }; + + if (helpName) payload.help = helpName; + if (allName) payload.all = allName; + if (monitorName) payload.monitor = monitorName; + if (typeName) payload.type = typeName; + if (dataStoreName) payload.dataStore = dataStoreName; + if (tmuxName) payload.tmuxid = tmuxName; + if (portName) payload.port = portName; + if (appName) payload.app = appName; + if (programName) payload.prog = programName; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamlist`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +} + +// ex: zx wrapper.mjs jamkill +// Validate and process the arguments +if (endpointArgs[0] === "jamkill") { + + // Get the parameters without value. + const helpArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--help")); + const allArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--all")); + const remoteArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--remote")); + + // Get index of parameter with value if present + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app==")); + const progArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--prog==")); + const portArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--port==")); + + + let helpName, allName, remoteName, typeName,dataStoreName,tmuxName, portName, appName, programName; + + // If parameter without value is present + if(helpArgIndex != -1) {helpName = "help"}; //Help + if(allArgIndex != -1) {allName = "all"}; //All + if(remoteArgIndex != -1) {remoteName = "remote"}; //Remote + + // Extract values of parameters with values if present + if (appArgIndex != -1) {appName = endpointArgs[appArgIndex].split("==")[1];} // Extract app + if (progArgIndex != -1) {programName = endpointArgs[progArgIndex].split("==")[1];} // Extract prog + if (portArgIndex != -1) {portName = endpointArgs[portArgIndex].split("==")[1];} // Extract port + + // Construct the JSON payload + let payload = { + }; + + if (helpName) payload.help = helpName; + if (allName) payload.all = allName; + if (remoteName) payload.remote = remoteName; + if (appName) payload.app = appName; + if (programName) payload.prog = programName; + if (portName) payload.port = portName; + + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamkill`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +} + +// ex: zx wrapper.mjs jamterm +// Validate and process the arguments +if (endpointArgs[0] === "jamterm") { + + const tmuxIdArg = endpointArgs[1] + + //Get if the index of all + const allArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--all")); + + // Get the index of a parameter with a value + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app==")); + const progArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--prog==")); + const portArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--port==")); + const paneArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--pane=")); + const tmerArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("-t ")) + + let allName, appName, progName, portName, paneName, termNum; + + // Use all if present + if(allArgIndex != -1) {allName = "all"}; //All + + // Extract the value of argument if present + if (appArgIndex != -1) {appName = endpointArgs[appArgIndex].split("==")[1];} // Extract app + if (progArgIndex != -1) {progName = endpointArgs[progArgIndex].split("==")[1];} // Extract prog + if (portArgIndex != -1) {portName = endpointArgs[portArgIndex].split("==")[1];} // Extract port + if (paneArgIndex != -1) {paneName = endpointArgs[paneArgIndex].split("=")[1];} // Extract pane + + + // Construct the JSON payload + let payload = { + }; + + if (allName) payload.all = allName; + if (appName) payload.app = appName; + if (progName) payload.prog = progName; + if (portName) payload.port = portName; + if (paneName) payload.pane = paneName; + + if (tmuxIdArg) payload.tmux_id = tmuxIdArg; + if (termNum) payload.terminal_number = termNum; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jamterm`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +} + + +// ex: zx wrapper.mjs djambatch jt1.jxe --device_num=5 --app=DEMO2 --bg +// Validate and process the arguments +if (endpointArgs[0] === "djambatch") { + + // Get index of parameters with a value associated with it + const deviceNumArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--device_num=")); + const appArgIndex = endpointArgs.findIndex((arg) => arg.startsWith("--app=")); + + + let deviceNumName, appName; + + + // If the parameter with value is present, extract the value + if (deviceNumArgIndex != -1) {deviceNumName = endpointArgs[deviceNumArgIndex].split("=")[1];} // Extract device_num + if (appArgIndex != -1) {appName = endpointArgs[appArgIndex].split("=")[1];} // Extract app + + + // Construct the JSON payload + let payload = { + device_num: deviceNumName, + app: appName + }; + + // Send the POST request to the server + const endpoint = `http://${serverIP}:3000/jambatch`; + fetch(endpoint, { + method: "POST", + headers: { "Content-Type": "application/json", + "x-ssh-public-key": sshPublicKey, + }, + body: JSON.stringify(payload), + }) + .then(async (response) => { + // Ensure response status is OK + if (!response.ok) { + const errorText = await response.text(); // Read error message from server + throw new Error(`HTTP error! Status: ${response.status}, Response: ${errorText}`); + } + + // Handle streaming response with Node.js readable stream + console.log("Streaming response:"); + response.body.on("data", (chunk) => { + process.stdout.write(chunk.toString()); + }); + response.body.on("end", () => { + console.log("\nStream finished."); + }); + }) + .catch((error) => { + console.error("Error sending request:", error.message); + }); +}