From ce1a2e32aa5316ed52612756ea363791513d5fa8 Mon Sep 17 00:00:00 2001 From: Alain Bryden <2285037+alainbryden@users.noreply.github.com> Date: Wed, 16 Oct 2024 21:43:27 -0300 Subject: [PATCH] Fix #375 and Fix #376 - backdoor-all-servers improvements - Reduced RAM footprint by using ram-dodging when connecting to servers. - Prevent multiple instances - Improve logging, especially of errors --- Tasks/backdoor-all-servers.js | 51 +++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/Tasks/backdoor-all-servers.js b/Tasks/backdoor-all-servers.js index e1132182..418707d6 100644 --- a/Tasks/backdoor-all-servers.js +++ b/Tasks/backdoor-all-servers.js @@ -1,21 +1,26 @@ -import { getNsDataThroughFile, getFilePath, log } from '../helpers.js' +import { getNsDataThroughFile, getFilePath, instanceCount, log, getErrorInfo } from '../helpers.js' const spawnDelay = 50; // Delay to allow time for `installBackdoor` to start running before a background script connects back to 'home' -/** @param {NS} ns - * Scan all servers, backdoor anything that can be backdoored, and leave a file to indicate it's been done +/** Scan all servers, backdoor anything that can be backdoored, and leave a file to indicate it's been done * Requires: SF-4.1 **/ -export let main = async ns => { - let anyConnected = false; +/** @param {NS} ns **/ +export async function main(ns) { + let notAtHome = false; try { - let servers = ["home"], - routes = { home: ["home"] }, - myHackingLevel = ns.getHackingLevel(); + // Prevent multiple instances of this script from being started + if (await instanceCount(ns, "home", false, false) > 1) + return log(ns, 'Another instance is already running. Shutting down...'); + + let servers = ["home"]; + let routes = { home: ["home"] }; + let myHackingLevel = ns.getHackingLevel(); // Scan all servers and keep track of the path to get to them ns.disableLog("scan"); for (let i = 0, j; i < servers.length; i++) for (j of ns.scan(servers[i])) if (!servers.includes(j)) servers.push(j), routes[j] = routes[servers[i]].slice(), routes[j].push(j); + // Filter out servers that cannot or should not be hacked / backdoored ns.disableLog("getServerRequiredHackingLevel"); let hackableServers = servers.filter(s => s != "home" && !s.includes("hacknet-") && !s.includes("daemon")) /*or whatever you name your purchased servers*/ @@ -26,15 +31,19 @@ export let main = async ns => { let toBackdoor = await getNsDataThroughFile(ns, `ns.args.filter(s => !ns.getServer(s).backdoorInstalled)`, '/Temp/servers-to-backdoor.txt', hackableServers); let count = toBackdoor.length; + // Early exit condition if there are no servers left to backdoor ns.print(`${count} servers have yet to be backdoored.`); if (count == 0) return; + // Early exit condition if there are no servers we can currently backdoor ns.print(`${toBackdoor.filter(s => ns.hasRootAccess(s)).length} of ${count} servers to backdoor are currently rooted.`); toBackdoor = toBackdoor.filter(s => myHackingLevel > ns.getServerRequiredHackingLevel(s)); ns.print(`${toBackdoor.length} of ${count} servers to backdoor are within our hack level (${myHackingLevel}).`); toBackdoor = toBackdoor.filter(s => ns.hasRootAccess(s)); ns.print(`${toBackdoor.length} of ${count} servers to be backdoored are rooted and within our hack level (${myHackingLevel})`); + if (toBackdoor.length == 0) return; + // Collect information about any servers still being backdoored (from a prior run), so we can skip them let scriptPath = getFilePath('/Tasks/backdoor-all-servers.js.backdoor-one.js'); let currentScripts = ns.ps().filter(s => s.filename == scriptPath).map(s => s.args[0]); @@ -44,25 +53,33 @@ export let main = async ns => { continue; } ns.print(`Hopping to ${server}`); - anyConnected = true; - for (let hop of routes[server]) - ns.singularity.connect(hop); + notAtHome = true; // Set a flag to get us back home if we encounter an error + const success = await getNsDataThroughFile(ns, + 'ns.args.reduce((success, hop) => success && ns.singularity.connect(hop), true)', + '/Temp/singularity-connect-hop-to-server.txt', routes[server]); + if (!success) + log(ns, `ERROR: Failed to hop to server ${server}. Backdoor probably won't work...`, true, 'error'); if (server === "w0r1d_d43m0n") { ns.alert("Ready to hack w0r1d_d43m0n!"); + log(ns, "INFO: Sleeping forever to avoid multiple instances navigating to w0r1d_d43m0n."); while (true) await ns.sleep(10000); // Sleep forever so the script isn't run multiple times to create multiple overlapping alerts } ns.print(`Installing backdoor on "${server}"...`); // Kick off a separate script that will run backdoor before we connect to home. var pid = ns.run(scriptPath, 1, server); if (pid === 0) - return ns.print(`Couldn't initiate a new backdoor of "${server}"" (insufficient RAM?). Will try again later.`); + return log(ns, `WARN: Couldn't initiate a new backdoor of "${server}" (insufficient RAM?). Will try again later.`, false, 'warning'); await ns.sleep(spawnDelay); // Wait some time for the external backdoor script to initiate its backdoor of the current connected server - ns.singularity.connect("home"); + const backAtHome = await getNsDataThroughFile(ns, 'ns.singularity.connect(ns.args[0])', null, ["home"]); + if (backAtHome) + notAtHome = false; } - } catch (err) { - ns.tprint(String(err)); + } + catch (err) { + log(ns, `ERROR: ${ns.getScriptName()} Caught an unexpected error:\n${getErrorInfo(err)}`, false, 'error'); } finally { - if (anyConnected) - ns.singularity.connect("home"); + // Try to clean-up by re-connecting to home before we shut down + if (notAtHome) + await getNsDataThroughFile(ns, 'ns.singularity.connect(ns.args[0])', null, ["home"]); } }; \ No newline at end of file