Run a .bat, .cmd, or PowerShell script on Windows
Name the interpreter explicitly and pass your script to it as an argument. Do not point websocketd at the script file on its own.
For a .bat or .cmd batch file, the interpreter is cmd.exe, and
/c tells it to run the file and then exit:
websocketd.exe --port=8080 cmd.exe /c C:\scripts\count.bat
For a .ps1 PowerShell script, the interpreter is powershell.exe, and
-File tells it to run the file:
websocketd.exe --port=8080 powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\scripts\count.ps1
Use pwsh.exe in place of powershell.exe for PowerShell 7 and later.
-ExecutionPolicy Bypass is needed because a default PowerShell
installation refuses to run unsigned local script files. -NoProfile
skips the user's profile script, which would otherwise run first and
can write its own text to stdout, mixing startup noise into
your script's messages.
A batch file to try it with:
@echo off
for /L %%i in (1,1,5) do (
echo %%i
timeout /t 1 /nobreak > nul
)
Why the interpreter has to be named
On Unix, a script file can say which interpreter runs it. The first line
holds a shebang, written #! followed by a path, as in
#!/usr/bin/env python3. The Unix kernel reads those two characters
when it is asked to execute the file, and launches the named interpreter
with the file as its argument.
Windows has no equivalent. The shebang is a kernel feature, and the
Windows kernel does not implement it. A #! line at the top of a file
on Windows is a comment, or a syntax error, depending on the
language.
Windows decides what runs a file from its extension instead, through a registry association. That association is a property of the machine's configuration, not of the file, and it is not guaranteed to be present or correct in the account and session that websocketd is running under. This is a recurring cause of a script that runs perfectly when double-clicked and fails to start under websocketd.
Naming cmd.exe or powershell.exe yourself removes the question. You
are no longer asking Windows to work out what to run; you are telling
it.
Give the interpreter a full path
websocketd resolves the command you give it by searching PATH, the
list of directories the operating system looks in for an executable.
Two things make that search less predictable on Windows than on Unix.
The first is that names differ between installations. Node.js, for
example, installs its executable as node.exe under some methods, while
documentation and scripts written elsewhere refer to it as nodejs. A
name that works on a colleague's machine can find nothing on yours, and
websocketd reports only that it could not locate the command.
The second is that a different program with the same name can be earlier
in PATH and win the search. Then websocketd starts successfully and
runs the wrong program, which is the harder failure to diagnose because
nothing reports an error.
Give the full path to the interpreter and neither can happen:
websocketd.exe --port=8080 "C:\Program Files\nodejs\node.exe" C:\scripts\echo.js
Your script gets no signal on disconnect
On Unix, websocketd tears a process down in stages when a client
disconnects. It closes the process's stdin, then sends
SIGINT, then SIGTERM, then SIGKILL, pausing between each. A
signal is a Unix notification that a process can catch and act on,
so those middle stages give a well-behaved program a window to save
state and exit cleanly.
Windows has no equivalent mechanism for one process to send SIGINT or
SIGTERM to another. websocketd still attempts both stages, and both
fail; you will see the failures logged as errors. The process is then
terminated forcibly. Your script gets no window in which to clean up,
and there is no fix for this, because there is no Windows facility to
use instead.
Closing stdin is the one part of the sequence that works everywhere, and it happens first. If your script needs to do anything on disconnect, have it watch for end-of-file on stdin rather than for a signal. That approach behaves the same on every platform.
Windows also has no process groups in the Unix sense, so websocketd cannot sweep up processes that your script started. Anything your script launches is left running unless your script stops it itself.
Next
- Platform support is the factual list of what differs on Windows.
- Process lifecycle has the full teardown sequence and its timings, and what a long-running program should do about it.
- Output buffering applies on Windows exactly as it does elsewhere. If your script runs but sends nothing, that page and the language page for whatever the script is written in are the place to look.