Ad-hoc scripts still need a paper trail
SSH in, run the fix, close the terminal. It worked, and six weeks later nobody can say what happened. What a script library and a recorded run change about that.
The most common piece of automation in any infrastructure team is not in a repository. It is a command somebody ran once, from their own terminal, against a machine that was misbehaving. It worked. The terminal got closed. That is the entire lifecycle.
I am not going to pretend this is avoidable. Sometimes a box needs a thing done to it right now and the correct response is to do the thing. The problem is not that people run ad-hoc commands. It is that the run leaves nothing behind, so six weeks later, when the same box misbehaves in the same way, the knowledge that would fix it in thirty seconds exists only in one person’s shell history and possibly not even there.
Give the script somewhere to live
The first change is that the script stops being something you remember and becomes something that exists.
Each entry carries its terminal type, so a PowerShell script and a Node script sit in the same library without either pretending to be the other. When you create one you choose whether it runs as an inline command or gets written out as a script file first, and which shell it runs under: Command, PowerShell, Git Bash or Bash.
The two columns I would not have thought to ask for are Timeout and Last running Time. A timeout on an ad-hoc command is the difference between a script that hangs and a script that fails, and those need very different responses at 2am. Last running Time tells you whether the thing in front of you is a script the team actually uses or one that somebody wrote in March and everyone has quietly stopped trusting.
Then there is the approval state, and the counters above the table that track it. A script that can execute arbitrary commands across a customer’s fleet is a fairly serious object to leave lying around, and the library treats it that way: written, then approved, then runnable.
A run is attached to a reason
The second change is what happens when you actually execute one.
Customer is mandatory, which in a multi-tenant setup is the difference between a scoped action and an accident. Title is mandatory too, so every run has a human-readable name attached rather than being identifiable only by its command.
Ticket Ref is optional, and I think it is the most interesting field on the form. It costs nothing to fill in and it is the thing that connects a command that ran on a machine to the reason anyone wanted it to. Six weeks later, that field is the difference between “somebody ran a PowerShell script on this host in August” and a ticket explaining what was wrong and what this was meant to do about it.
Apply Parallelly decides whether the targets are hit at once or in sequence. Parallel is the default and is usually what you want for something read-only. Sequential is what you want when the script restarts a service and the machines behind it are meant to stay collectively available, which is exactly the kind of decision that gets made badly when the tool does not offer it.
Executing then asks you to confirm. A dialog reading “Are you sure you want to execute the remote script?” is not sophisticated, but it sits between a moment of inattention and a fleet-wide command, and I have never regretted one being there.
Runs are rows, and they have states
A run moves from READY to EXECUTING to SCRIPT COMPLETED, and each one gets its own code. Running the same script twice produces two records rather than overwriting one, which sounds obvious and is the thing shell history fundamentally cannot do.
While a run is executing there is a live console, in the same shape as the release console covered in a release is not finished when it is applied. For a one-minute script that counts for less than it does on a release, but the useful case is the one where a script that normally takes ten seconds is still going after two minutes and you would like to know which machine is holding it up.
The receipt
Afterwards, the run has a summary, and it is what justifies the whole apparatus.
Devices attempted. Scripts run. Completed, failed and in progress as separate counts rather than one overall status. Then the individual machine, identified properly, and the named task underneath it with its own state.
The reason to care about the split is partial failure, which is the normal outcome of running anything across a real fleet. A script that ran on thirty-eight of forty machines is not a success and it is not a failure, and a tool that reports it as either is lying to you. Two machines were offline, or busy, or in a state the script did not anticipate, and the useful output is which two.
The run also carries per-device stats, the agent logs, the task list and a history. Agent logs is where you end up when a script failed for a reason the script itself did not report, which is most of them.
Three tools, three different problems
Policies, releases and scripts overlap enough to be confusing, so it is worth saying plainly which is for what.
A software policy is for a condition you want to hold indefinitely. It re-evaluates on an interval and corrects drift without anyone asking, which we wrote up in software policies: desired state, not one-off installs.
A release is for a versioned artefact going to machines under an approval, with a verify stage and a rollback.
A remote script is for the thing that does not fit either. A diagnostic you need the output of. A one-time cleanup. A fix you are still working out the shape of and may well turn into a policy once you do.
That third category is not going away, and pretending otherwise is how teams end up with an “automation strategy” that everybody bypasses at 2am. The realistic goal is not to eliminate the ad-hoc command. It is to make running one through the tool cheaper than running it through SSH, so the audit trail happens as a side effect of the path of least resistance rather than as a discipline anybody has to maintain.
There is a scheduling side to this as well, where scripts run on a cron or rate schedule, or off a trigger event, rather than because someone pressed a button. Each schedule keeps its own run history. That deserves its own post rather than a paragraph here.
The RMM overview covers how scripting sits alongside monitoring and patching, and RMM automation recipes has the practical version of what teams actually automate first.
LynxTrac is free forever for up to 2 servers, no card required. If you want to try it on real infrastructure instead of reading about it: app.lynxtrac.com.
Related posts
RMM automation recipes: workflows that save hours every week
Seven specific automations our customers run across their fleets, ranked by how often they fire and how much pager noise they prevent.
From alerts to auto-fix: building self-healing IT systems
Alerts that only notify you about a problem are half a solution. Teams use LynxTrac automations to turn those alerts into auto-remediation without waking a human.
10 essential IT automation workflows using LynxTrac
Here are ten IT automation workflows, from patch deploys to user onboarding, that teams stand up in their first week on LynxTrac.