#file-transfer #ssh #ping #character #shipping #host-port #speed-test #table-style #mb #encryption

app sshping

SSH-based ping that measures interactive character echo latency and file transfer throughput. Pronounced "shipping".

12 releases

Uses new Rust 2024

new 0.3.1 Apr 4, 2026
0.2.4 Apr 4, 2026
0.2.2 Aug 27, 2025
0.2.1 Jul 9, 2025
0.1.3 Jun 14, 2024

#35 in Value formatting

MIT license

81KB
2K SLoC

SSH ping

Crates.io Version Crates.io License Crates.io Total Downloads Crates.io Downloads (latest version) GitHub Repo stars

SSH-based ping that measures interactive character echo latency and file transfer throughput. Pronounced "shipping".

A continuation and re-work of the original ssh-ping in Rust.

Installation

Cargo

sshping is published on crates.io, you can install it with (first having rust toolchain installed):

cargo install sshping

Homebrew (macOS/Linux)

sshping is also available on Homebrew/Linuxbrew, you can install it with:

brew install TeddyHuang-00/app/sshping

Pre-built binaries

Pre-built binaries are available on the releases page. You can download the binary for your platform and put it in your $PATH.

From source

To install from source, you can clone the repository first:

git clone git@github.com:TeddyHuang-00/sshping.git
# Or
git clone https://github.com/TeddyHuang-00/sshping.git

# Then
cd sshping

Then build and install it with cargo:

cargo install --path .

Usage

Usage: sshping [OPTIONS] <TARGET>

Arguments:
  <TARGET>  [user@]host[:port]

Options:
  -f, --config <FILE>            Read the ssh config file FILE for options [default: ~/.ssh/config]
  -o, --format <FORMAT>          Output format [default: table] [possible values: table, json]
  -i, --identity <FILE>          Use identity FILE, i.e., ssh private key file
  -p, --password <PWD>           Use password PWD for authentication (not recommended)
  -T, --ssh-timeout <SECONDS>    Time limit for ssh connection in seconds [default: 10]
  -r, --run-tests <TEST>         Run TEST [default: both] [possible values: echo, speed, both]
  -c, --char-count <COUNT>       Number of characters to echo [default: 1000]
  -e, --echo-cmd <CMD>           Use CMD for echo command [default: "cat"]
  -t, --echo-timeout <SECONDS>   Time limit for echo test in seconds
  -s, --size <SIZE>              File SIZE for speed test [default: 8.0MB]
  -u, --chunk-size <CHUNK_SIZE>  Chunk SIZE for splitting file in speed test [default: 1.0MB]
  -z, --remote-file <FILE>       Remote FILE path for speed tests [default: /tmp/sshping-test.tmp]
  -b, --table-style <STYLE>      Table style for output [default: ascii] [possible values: empty, blank, ascii, psql, markdown, modern, sharp, extended, dots, rst, rounded, ascii-rounded, modern-rounded]
  -d, --delimiter <DELIMITER>    Specify delimiters to use (or None for not using) in big numbers [default: ,]
  -H, --human-readable           Use human-friendly units
  -k, --key-wait                 Wait for keyboard input before exiting
  -v, --verbose...               Show verbose output, use multiple for more noise
  -h, --help                     Print help (see more with '--help')
  -V, --version                  Print version

Examples

Ping a host from ssh config with human-readable output and modern table style with rounded corners:

$ sshping OverLAN -H -b modern-rounded
╭─────────┬───────────────┬─────────────╮
  Test   │    Metric     │   Result    │
├─────────┼───────────────┼─────────────┤
   SSH   │ Connect time  │ 49ms 775us  │
├─────────┼───────────────┼─────────────┤
         │    Average    │ 177us 731ns │
         ├───────────────┼─────────────┤
         │ Std deviation │ 59us 706ns  │
         ├───────────────┼─────────────┤
 Latency │    Median     │ 203us 263ns │
         ├───────────────┼─────────────┤
         │    Minimum    │ 11us 387ns  │
         ├───────────────┼─────────────┤
         │    Maximum    │ 270us 20ns  │
├─────────┼───────────────┼─────────────┤
         │    Upload     │  153 MB/s   │
  Speed  ├───────────────┼─────────────┤
         │   Download    │  89.2 MB/s  │
╰─────────┴───────────────┴─────────────╯

Ping a certain host with username and port, using _ as delimiter and a specific identity file:

$ sshping user@host:7890 -i ~/.ssh/id_rsa -d _
+---------+---------------+-----------------+
|  Test   |    Metric     |     Result      |
+---------+---------------+-----------------+
|   SSH   | Connect time  |  49_725_720ns   |
+---------+---------------+-----------------+
|         |    Average    |    10_268ns     |
|         +---------------+-----------------+
|         | Std deviation |     3_055ns     |
|         +---------------+-----------------+
| Latency |    Median     |     9_773ns     |
|         +---------------+-----------------+
|         |    Minimum    |     8_075ns     |
|         +---------------+-----------------+
|         |    Maximum    |    40_603ns     |
+---------+---------------+-----------------+
|         |    Upload     | 127_897_360 B/s |
|  Speed  +---------------+-----------------+
|         |   Download    | 94_500_777 B/s  |
+---------+---------------+-----------------+

Output results in JSON format:

$ sshping user@host -H -o json
{
  "echo_test": {
    "avg_latency": "12us 135ns",
    "char_sent": 1000,
    "max_latency": "70us 550ns",
    "med_latency": "10us 943ns",
    "min_latency": "6us 690ns",
    "std_latency": "4us 580ns"
  },
  "speed_test": {
    "download": {
      "size": "8.00 MB",
      "speed": "88.4 MB/s",
      "time": "90ms 516us"
    },
    "upload": {
      "size": "8.00 MB",
      "speed": "123 MB/s",
      "time": "64ms 781us"
    }
  },
  "ssh_connect_time": "35ms 998us"
}

Contributing

Contributions are welcome! Feel free to open an issue or a pull request. Anything from bug report to feature request to code contribution is appreciated.

Currently, there are a few things that can be added but haven't been yet. If you would like to help but don't know where to start, you can check this list below:

  • Table style customization
  • Unit tests
  • Man page generation
  • Shell autocompletion script generation
  • Packaging for various platforms
  • More SSH tests
  • Better error handling
  • Code optimization

FAQ

How to use public-private key pair for authentication?

Using public-private key pair is recommended. Provide the identity file (private key) path through the -i argument:

sshping user@host -i ~/.ssh/id_rsa

If your private key is encrypted with a passphrase, you can either:

  • Provide it via the -p flag: sshping user@host -i ~/.ssh/id_rsa -p "your-passphrase" (not recommended for security)
  • Let the tool prompt you interactively (recommended): When running in an interactive terminal, you'll be prompted to enter the passphrase securely

Authentication identity precedence is resolved per endpoint (target and each ProxyJump hop) in this order:

  1. SSH config IdentityFile from the matching Host block for that endpoint
  2. CLI --identity file
  3. Fallback key discovery/default auth attempts (for example default keys under ~/.ssh)

This means proxy hops can use their own configured keys while the target can use a different key or fall back.

What about password authentication?

Password authentication is supported but not recommended. If no public key authentication is configured, the tool will:

  • Use the password provided via -p flag if available
  • Prompt you interactively for a password for the specific user@host endpoint when running in an interactive terminal (recommended over -p flag)
  • Fail if neither is available or in non-interactive environments (scripts, CI/CD)

Why isn't XXX functionality of SSH supported?

Many features like BindAddress are currently not supported due to the limitation of upstream libraries.

If they got implemented in the upstream libraries, they will be added to this project as well. Or you can open a pull request to add them yourself!

Why isn't all my identity file in SSH config being used?

If more than one identity file is given in the configuration file, only the first one will be used. This is an opinionated design choice to keep the implementation simple.

Shell autocompletion doesn't work

sshping supports two completion engines:

  1. Runtime dynamic completion (recommended) with clap_complete::CompleteEnv:

    This is recommended because it stays in sync with the installed binary and supports dynamic candidates (for example SSH config hosts).

    • Bash:

      echo "source <(SSHPING_COMPLETE=bash sshping)" >> ~/.bashrc
      # Or source it directly in the current shell session:
      source <(SSHPING_COMPLETE=bash sshping)
      
    • Zsh:

      echo "source <(SSHPING_COMPLETE=zsh sshping)" >> ~/.zshrc
      # Or source it directly in the current shell session:
      source <(SSHPING_COMPLETE=zsh sshping)
      
    • Fish:

      echo "source (SSHPING_COMPLETE=fish sshping)" >> ~/.config/fish/config.fish
      # Or source it directly in the current shell session:
      source (SSHPING_COMPLETE=fish sshping)
      
    • Elvish:

      echo "eval (E:SSHPING_COMPLETE=elvish sshping | slurp)" >> ~/.elvish/rc.elv
      # Or source it directly in the current shell session:
      eval (E:SSHPING_COMPLETE=elvish sshping | slurp)
      
    • PowerShell:

      $env:SSHPING_COMPLETE = "powershell"
      echo "sshping | Out-String | Invoke-Expression" >> $PROFILE
      Remove-Item Env:\SSHPING_COMPLETE
      # Or source it directly in the current shell session:
      $env:SSHPING_COMPLETE = "powershell"
      sshping | Out-String | Invoke-Expression
      Remove-Item Env:\SSHPING_COMPLETE
      
    • Xonsh:

      Note: Xonsh support is currently not available in clap_complete, but it can be added using the following workaround

      1. Install fish shell and follow the fish instructions above to generate the completion script for fish shell.

      2. Install xontrib-fish-completer xontrib to enable sourcing fish completion scripts in xonsh.

      3. Load xontrib-fish-completer in your xonsh configuration:

        xontrib load fish_completer
        
  2. Static completion scripts generated at build time by build.rs (written under target/<profile>/completions).

    You can download the static files from releases page and source those manually if you prefer file-based setup.

Dependencies

~87–125MB
~2.5M SLoC