Some Unix Commands Fail with "<Command> Not Found", When Executed Using Python Paramiko Exec_Command

Some Unix commands fail with command not found, when executed using Python Paramiko exec_command

The SSHClient.exec_command by default does not run shell in "login" mode and does not allocate a pseudo terminal for the session. As a consequence a different set of startup scripts is (might be) sourced, than in your regular interactive SSH session (particularly for non-interactive sessions, .bash_profile is not sourced). And/or different branches in the scripts are taken, based on an absence/presence of TERM environment variable.

Possible solutions (in preference order):

  1. Fix the command not to rely on a specific environment. Use a full path to sesu in the command. E.g.:

    /bin/sesu test

    If you do not know the full path, on common *nix systems, you can use which sesu command in your interactive SSH session.

  2. Fix your startup scripts to set the PATH the same for both interactive and non-interactive sessions.

  3. Try running the script explicitly via login shell (use --login switch with common *nix shells):

    bash --login -c "sesu test"
  4. If the command itself relies on a specific environment setup and you cannot fix the startup scripts, you can change the environment in the command itself. Syntax for that depends on the remote system and/or the shell. In common *nix systems, this works:

    PATH="$PATH;/path/to/sesu" && sesu test
  5. Another (not recommended) approach is to force the pseudo terminal allocation for the "exec" channel using the get_pty parameter:

    stdin,stdout,stderr = ssh.exec_command('sesu test', get_pty=True)

    Using the pseudo terminal to automate a command execution can bring you nasty side effects. See for example Is there a simple way to get rid of junk values that come when you SSH using Python's Paramiko library and fetch output from CLI of a remote machine?


You may have a similar problem with LD_LIBRARY_PATH and locating shared objects.


See also:

  • Environment variable differences when using Paramiko
  • Certain Unix commands fail with "... not found", when executed through Java using JSch

Command executed with Paramiko does not produce any output

If you get no output on stdout, it is usually because the command fails to start.

Read stderr to check for any errors.

print(stderr.readlines())

Quite often the error is "<command> not found". For that see

Some Unix commands fail with "<command> not found", when executed using Python Paramiko exec_command


If you are connecting to a device, see also Executing command using Paramiko exec_command on device is not working.

how can I run python file in remote server using Paramiko?

Source of the issue:

There are different types of shell sessions that get run depending on how you connect to a remote (or local) machine. These different shell types "source" (or execute) different configuration files when they are launched. When you ssh into the remote server from your terminal, you connect to what's called an "interactive login shell"—it's "interactive" because you can interactively run and interrupt commands, and it's a "login shell" because it's the first shell launched after you logged in1.

Interactive Bash login shells source various files that typically (among other things) make additional commands available to you by adding directories containing executables to your $PATH. You mentioned conda, for example—when you install conda, it automatically adds some code to your .bash_profile to make it available when that file is sourced, which it is for interactive login shells2.

However, when you send a command over ssh the way you're doing with paramiko, that command is by default invoked in a noninteractive (non-login) shell. In this case, your configuration files are not sourced3, which is why the commands you expect to be available are not.

How to fix it:

The easiest way would be to simply change cli.exec_command(<command>) to cli.exec_command('/bin/bash -lc "<command>"'). The -l flag causes bash to behave as though it were invoked in a login shell, meaning it will source all the same configuration files it does when you ssh in from your terminal.

If you need an interactive shell, you could instead use cli.get_pty() and cli.invoke_shell(), but this isn't necessary for just running a Python script.

Finally, I highly recommend taking a look at spurplus. It's built on top of spur, which is in turn built on top of paramiko, and it adds some nice extra features in addition to being much easier to use.


1this is true for Linux systems. On MacOS, subsequent interactive shells you launch are also login shells.

2there are also interactive non-login shells, which instead source your .bashrc. Again, some of this is slightly different for non-Linux machines, as well as other shells like Zsh.

3unless you've specified a $BASH_ENV file.

Running database script with Paramiko fails with exit code

If a command does not work, when executed using Paramiko, debug it by reading its error output.

Use stderr.readlines() for that.


If the same command works in regular shell, but not in Paramiko, the problem is usually related to a different environment used by the SSH "exec" channel, which is used by SSHClient.exec_command. See:

  • Some Unix commands fail with "<command> not found", when executed using Python Paramiko exec_command
  • Environment variable differences when using Paramiko

SSHClient.exec_command() reported command not found

Based on your latest comments you should use the absolute path to mmdf when running the command:

client.exec_command("/the/path/to/mmdf mmfs1 --block-size auto")

To find out where mmdf is, manually login to the server and run:

which mmdf
# or
type -P mmdf


Related Topics



Leave a reply



Submit