Running remote SSH commands from Windows becomes predictable and scriptable with Plink, the command-line companion to PuTTY that fits neatly into Scheduled Tasks, deployment jobs, and health checks without dragging a terminal UI into the mix.

plink.exe uses the same connection engine as PuTTY, including saved sessions and the per-user cached host key database, so automated runs can reuse trusted fingerprints and connection settings instead of re-learning them on every execution.

Automation succeeds when prompts never appear, so host key trust and authentication must be made non-interactive before -batch is involved. Password prompts and “trust this host?” dialogs are the usual traps, and both are solvable with one-time host key caching plus key-based authentication (or an agent) for repeatable runs.

  1. Open Command Prompt in the same Windows user context used for automation.

    Plink stores cached host keys and saved sessions per Windows user profile, so Scheduled Tasks and service accounts often need a separate first-run cache.

  2. Cache the server host key once to avoid interactive prompts during batch runs.
    C:\>plink -ssh user@example.com
    The server's host key is not cached in the registry. You have no guarantee that the server is the computer you think it is.
    The server's ssh-ed25519 key fingerprint is:
    ssh-ed25519 255 SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abcd
    If you trust this host, enter "y" to add the key to PuTTY's cache and carry on connecting.
    Store key in cache? (y/n) y
    user@example.com's password:
    ##### snipped #####

    Accepting the wrong host key enables man-in-the-middle attacks, so compare the fingerprint with a trusted source before caching it.

  3. Run a one-off remote command in non-interactive mode using a .ppk private key.
    C:\>plink -batch -ssh -i C:\Keys\id_ed25519.ppk user@example.com hostname
    web-01

    -batch disables all prompts, so the connection fails if the host key is not cached or the private key requires a passphrase prompt, so use Pageant for passphrase-protected keys.

    Pin the expected host key fingerprint in scripts with -hostkey to avoid relying on a cached registry entry:

    C:\>plink -batch -ssh -hostkey "ssh-ed25519 255 SHA256:AbCdEfGhIjKlMnOpQrStUvWxYz0123456789abcd" -i C:\Keys\id_ed25519.ppk user@example.com hostname

    Avoid -pw for automation because command-line passwords can be exposed via process listings and logs.

  4. Create a command file such as C:\Scripts\commands.txt containing one remote command per line.
    hostname
    uptime
    df -h /

    Each line is executed sequentially on the remote host using the default remote shell.

  5. Execute the command file with Plink using the -m option.
    C:\>plink -batch -ssh -i C:\Keys\id_ed25519.ppk -m C:\Scripts\commands.txt user@example.com
    web-01
     10:22:41 up 23 days,  4:18,  1 user,  load average: 0.00, 0.01, 0.02
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/vda1        40G   11G   28G  29% /

    Redirect stdout and stderr to files for logging in Scheduled Tasks: > C:\Logs\plink.out 2> C:\Logs\plink.err.

  6. Reuse a saved PuTTY session profile with the -load option to keep connection settings out of scripts.
    C:\>plink -batch -load "prod-web-01" uptime
     10:23:10 up 23 days,  4:19,  1 user,  load average: 0.00, 0.01, 0.02

    The saved session can hold the host name, port, username, proxy settings, and key path configured in PuTTY.

  7. Check the Plink exit code in scripts using ERRORLEVEL to detect authentication and remote command failures.
    C:\>plink -batch -load "prod-web-01" "systemctl is-active nginx"
    active
    
    C:\>echo %ERRORLEVEL%
    0
    
    C:\>plink -batch -load "prod-web-01" "false"
    
    C:\>echo %ERRORLEVEL%
    1

    Non-zero exit codes are typically safe to treat as failures for automation retries and alerting.