Coder Social home page Coder Social logo

spur.py's People

Contributors

beenje avatar mwilliamson avatar viotti avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spur.py's Issues

No output when using 'service service-name status' on a stopped service

`try:
        shell = spur.SshShell(hostname=server_address,
                              username='abc',
                              password='xyz', missing_host_key=spur.ssh.MissingHostKey.accept, connect_timeout=100)

        with shell:
            result = shell.run(['service', service_name, 'status'])
            print result.output`

So this works perfect is a service is running. But if a service is stopped, does return/print anything.

  1. Tried using result.stderr_output but still no output.
  2. Works perfectly over plain ssh
  3. Works good if the same service is running and command is called.
  4. Does return output when using pxssh

SunOS Missing tar Option used

Hi mwilliamson,

I'm trying to copy a file. The only method I can see to use is (undocumented, I know):
shell.upload_dir(original_dir, to_dir, ignore=(['.c*']))

I know paramiko can do this, but I much prefer spur.py because it's way easier - thanks!

spur.results.RunProcessError: return code: 1
output: 
stderr output: tar: z: unknown function modifier
Usage: tar {c|r|t|u|x}[BDeEFhilmnopPqTvw@[0-7]][bfk][X...] [blocksize] [tarfile] [size]       [exclude-file...] {file | -I include-file | -C directory file}...

$ uname -a
SunOS atrcus1042 5.10 Generic_147440-19 sun4u sparc SUNW,SPARC-Enterprise

It's really old, I know! It's what I have to work with.... Did I miss a better way to copy files across? It's binary data, I've used shell.open with strings no problem. Thanks!

Disable logging from Paramiko when using Spur

Hello,

Is it possible to disable Paramiko's logging to debug when using Spur? I cannot seem to find an option to do this. The reason I'm trying to do this is I'm using logging module to log my own messages, and it get's pretty clustered with all of the Paramiko's logs.

Is there any other way to disable the logs (at least on debug level) from Paramiko when using Spur other than adding logging.getLogger("paramiko").setLevel(logging.ERROR) in every file where Spur is used?

Spur SshShell expects to be connected to a bash(like) session

Right now when you connect to a machine with a custom shell (which maybe is there to reject connections), spur's spawn function does not take into account that the shell may not be bash. In my testing this results in raising an exception in _read_int_line as spur tries to parse the pid or which command output (all this in spur/ssh.py).

This came up for us when we tried using spur to connect to an ec2 machine with the root user. The AMI in question had a custom shell which essentially looks like this (my version not theirs, but it accomplishes the same thing):

#!/bin/bash
echo 'Please login as the user "ubuntu" rather than the user "root".'
exit 1

Since the connection successfully opens, spur goes ahead and runs the command and then fails to parse the rejection line as an int and raises a ValueError:

ValueError: invalid literal for int() with base 10: b'Please login as the user "ubuntu" rather than the user "root".'

I am not sure what the correct fix is here, but it seems that somehow validating that the receiving process is /bin/bash (or a bash variant) would be good.

For now we are catching the ValueError in a spawn wrapper, but this is not ideal since it may mask other real ValueErrors in the future.

Thanks!

Private key pair passphrase

Hello,

I'm investing using spur with a small project. Does it support loading and providing a passphrase on a private key pair? I was unable to get it to work when providing both the password and private_key_file option to spur.SshShell. I keep getting authentication failed. However, running a test from the command line verifies that the key and passphrase work.

Thanks,
Jay

SSH connection error for script that runs for long time

So I have a script where I need to connect to a few nodes sequentially to run a bunch commands that can take a few hours to complete. For each node I do something like following

for node in nodes:
    tunnel = spur.SshShell(hostname=node, username='xyz')
    with tunnel:
        for cmd in cmds:
            result = tunnel.run(cmd)
           do_something()

I run the above script in a screen session. The issue I am seeing is that all commands are run succesfully for first node but after that following exception is raised

Original error: No authentication methods available
Traceback (most recent call last):
  File "xyz.py", line 219, in <module>
    main()
  File "xyz.py", line 55, in __init__
    self.nodes = self.get_nodes_info()
  File xyz, line 63, in get_nodes_info
    tunnel = ssh_tunnel(str(self.seed_ip))
  File "xyy", line 29, in ssh_tunnel
    tunnel.run(["uptime"])
  File "/usr/local/lib/python2.7/dist-packages/spur/ssh.py", line 162, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File "/usr/local/lib/python2.7/dist-packages/spur/ssh.py", line 173, in spawn
    channel = self._get_ssh_transport().open_session()
  File "/usr/local/lib/python2.7/dist-packages/spur/ssh.py", line 251, in _get_ssh_transport
    raise self._connection_error(error)
spur.ssh.ConnectionError: Error creating SSH connection
Original error: No authentication methods available

I also noticed that in this same screen session I can not use spur at all. Even in python interpreter keep on hitting the same error. However I can connect to the same node in a different screen session. It seems like the fact that commands take a long time to complete and thus need to keep session active for a long time messes up spur or paramiko.

Another scenario that I tried was to open a different screen session and replaced the commands that I need to run with simpler bash commands. In this case the commands were executed on all nodes without any issues.

sys.stdout encoding error

Hi,

if you use stdout=sys.stdout while running command using Python 3, you will get such error:

  File "/home/alex/.virtualenvs/XXX/lib/python3.4/site-packages/spur/io.py", line 82, in _capture_output
    self._file_out.write(output)
TypeError: must be str, not bytes

To fix this, you need to decode child's output at io._ContinuousReader._capture_output():82:

                if self._file_out is not None:
                    self._file_out.write(output.decode('utf-8'))

Thanks.

When sending "poweroff" command, process hangs

I use the following code to send a poweroff command to a remote machine. I catch the resulting exception otherwise I get RunProcessError. I am trying to test poweroff + wake on lan on a unit repeatedly so I run this in a loop about 100-200 times. I usually the process hang around the 30th iteration:

def run_command(cmd, host):
    shell = spur.SshShell(hostname=host, username="test",
            password="test", missing_host_key=spur.ssh.MissingHostKey.accept)

    with shell:
        try:
            result = shell.run(cmd)
            log.info(result.output)
        except spur.results.RunProcessError:
            log.info("Probably a poweroff command")
        else:
            return result.output

for i in range(count):
    log.info("Powering off") # LAST MESSAGE SEEN ON LOG
    run_command(["sudo", "poweroff"], host) # GETS STUCK IN THIS FUNCTION
    time.sleep(60) # wait for unit to shutdown properly

    # Wake on lan and wait
    log.info("Sending wol magic packet")
    wol.send_magic_packet("00:1f:f2:09:43:e5")
    time.sleep(60) # wait for unit to come up

spur hangs after child exits in local process

In some circumstances (I haven't discovered what the conditions are) when I use local shell it hangs. The child process is dead but spur has not called waitpid (i.e. child is zombie).

The code calling the subprocess is more or less following:

import spur

local = spur.LocalShell()
spur.run(["git", "push", "ssh://someserver/some/git/repo.git"], cwd="some/local/git/repo", stdout=sys.stdout, stderr=sys.stderr)

troubles getting started with spur

I run this example with correct hostname nad port and credentails and i get the error stated below.

"spur.ssh.ConnectionError: Error creating SSH connection
Original error: [Errno -2] Name or service not known"

Using a debugger I see that it does get the shell.
But the error is raised on shell.run()

import spur
shell = spur.SshShell(hostname="1.2.3.4:123",username="bla", password="bla")
with shell:
result = shell.run(["echo", "-n", "hello"])
print result.output

Also if I try to use
spur.SshShell(hostname="1.2.3.4", port=123,username="bla", password="bla")
it fails saying "Original error: Server '1.2.3.4:123' not found in known_hosts" but does not complain if i use this-->
spur.SshShell(hostname="1.2.3.4:123",username="bla", password="bla")

Command not found: hostname. Check that echo is installed and on $PATH

Hi there,

Trying to execute the command 'hostname' on an ESXi server but it fails with the error message:
Command not found: hostname. Check that echo is installed and on $PATH

The code:

import spur

shell = spur.SshShell(hostname="ESXI-SERVER", username="user1", password="pass1", missing_host_key=spur.ssh.MissingHostKey.accept)
with shell:
    result = shell.run(["hostname"])
print result.output

When executing the command manually using SSH getting the output from the server.

ssh user1@ESXI-SERVER
Password: 
The time and date of this login have been sent to the system logs.

VMware offers supported, powerful system administration tools.  Please
see www.vmware.com/go/sysadmintools for details.

The ESXi Shell can be disabled by an administrative user. See the
vSphere Security documentation for more information.
~ # hostname
ESXI-SERVER
~ # 

Kind regards,
Ilias

cwd to non existent directory doesn't fail on SshShell

Changing to a non existent directory with a local shell raises a FileNotFoundError:

>>> shell = spur.LocalShell() 
>>> shell.run(['mkdir', '-p', 'foo'], cwd='/some/silly/path')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/benjamin/Dev/spur/spur.py/spur/local.py", line 111, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File "/Users/benjamin/Dev/spur/spur.py/spur/local.py", line 68, in spawn
    **self._subprocess_args(command, *args, **kwargs)
  File "/Users/benjamin/miniconda/envs/spur/lib/python3.5/subprocess.py", line 947, in __init__
    restore_signals, start_new_session)
  File "/Users/benjamin/miniconda/envs/spur/lib/python3.5/subprocess.py", line 1551, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: '/some/silly/path'

But it doesn't with a SshShell. The command is executed anyway:

>>> ssh_shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
>>> r = ssh_shell.run(['mkdir', '-p', 'foo'], cwd='/some/silly/path')
>>> r.return_code
0
>>> r = ssh_shell.run(['ls', '-ld', 'foo'])
>>> r.output
b'drwxr-xr-x 2 pi pi 4096 Aug  2 20:36 foo\n'

In this case, the directory is created in the home directory of the remote user.
The command should not be executed.

Closing SSH connections

After successfully executed my commands, I need to close the SSH connection but I don't no how. I don't know if it is a issue or I don't find the way to close the session.
I checked with "netstat" and the SSH connection remains established until I close the python interpreter.

Could you give me some ideas?

Server 'localhost' not found in known_hosts

import spur
shell = spur.SshShell(hostname="localhost", username="bob", password="password1")
with shell:
result = shell.run(["echo", "-n", "hello"])
print(result.output) # prints hello

Traceback (most recent call last):
File "help.py", line 5, in
result = shell.run(["echo", "-n", "hello"])
File "build/bdist.linux-x86_64/egg/spur/ssh.py", line 160, in run
File "build/bdist.linux-x86_64/egg/spur/ssh.py", line 171, in spawn
File "build/bdist.linux-x86_64/egg/spur/ssh.py", line 249, in _get_ssh_transport
spur.ssh.ConnectionError: Error creating SSH connection
Original error: Server 'localhost' not found in known_hosts

what is the matter?

persistant connections ? y/n & a note

I'm liking spur very

thanks for the effort

My question is I'm in a situation where I'd like to keep a ssh connection open
so that each new command sent does not have to reconnect and authenticate (to save time)

I've only started with spur (and even python)
but is there a "keep active" command available?
or some sort of pattern for that?

Also I bumped my head against the "shell_type=spur.ssh.ShellTypes.minimal" problem with embedded systems on a Raspberry Pi..
Adding that fixed all my problems [yay]
it might be a good thing to add to the readme that RPi users should use the "shell_type=spur.ssh.ShellTypes.minimal" directive

thanks again

WH

fping command on remote on unreachable ip throws exception

cmd = fping -c 2 -q 10.152.126.25 -s
shell = spur.SshShell(hostname=ip, username="root", password="foo")
x = shell.run(cmd.split(" "))
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 156, in run
return self.spawn(_args, *_kwargs).wait_for_result()
File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 353, in wait_for_result
self._result = self._generate_result()
File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 365, in _generate_result
stderr_output
File "/usr/local/lib/python2.7/site-packages/spur/results.py", line 9, in result
raise result.to_error()
spur.results.RunProcessError: return code: 1
output: b''
stderr output: b'10.152.126.25 : xmt/rcv/%loss = 2/0/100%\n\n 1 targets\n 0 alive\n 1 unreachable\n 0 unknown addresses\n\n 0 timeouts (waiting for response)\n 2 ICMP Echos sent\n 0 ICMP Echo Replies received\n 0 other ICMP received\n\n 0.00 ms (min round trip time)\n 0.00 ms (avg round trip time)\n 0.00 ms (max round trip time)\n 1.517 sec (elapsed real time)\n\n'

I would except x to return with returncode 1 and output instead of the exception

Writing str command instead of list

If i'll use spur module in my project. I want to write shell commands in str variable instead of the list. I think it's easy and fast way to do this.

import spur

shell = spur.LocalShell()
cmd = "echo -n hello"
result = shell.run(cmd)
print(result.output) # prints hello

Do you accept PR like below for local.py, shell.py etc. ?

encoding = kwargs.pop("encoding", None)
cwd = kwargs.get('cwd')
command = command.split() # Return a list of the words in the string
command_in_cwd = self._shell_type.generate_run_command(command, *args, store_pid=store_pid, **kwargs)

Unable to run multiple commands with pipe

I'm trying to form complexer commands by concatenating them via pipe symbol and execute them through SshShell.

Commands look like this, i.e.:

atq -q D | cut -f1 | xargs at -q D -c | grep user

I tried to construct a command list for SshShell but nothing seems to work. Isn't it possible at the moment to concat commands via piping?

Optional username

Paramiko does not require the username to be set, it would be nice if it was optional in spur too.

get ssh transport function error when connection to cisco device

I have a simple script used to test spur's functionality. I can successfully connect to linux servers, but not to my cisco router. It fails with the message "Original error: No existing session", and is raised by _get_ssh_transport(). I have tried with password and ssh keys, the result is the same. Any suggestions? The full trace is below:

$ cat test.py
import spur

Local

shell = spur.LocalShell()
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello

Remote

shell2 = spur.SshShell(
hostname="10.99.9.1",
username="root",
password="root",
missing_host_key=spur.ssh.MissingHostKey.warn
)
result2 = shell2.run(["echo", "-n", "hello","from","remote"])
print result2.output # prints hello

$ python test.py
hello
No handlers could be found for logger "paramiko.transport"
Traceback (most recent call last):
File "test.py", line 14, in
result2 = shell2.run(["echo", "-n", "hello","from","remote"])
File "/usr/lib/python2.7/site-packages/spur/ssh.py", line 70, in run
return self.spawn(_args, *_kwargs).wait_for_result()
File "/usr/lib/python2.7/site-packages/spur/ssh.py", line 80, in spawn
channel = self._get_ssh_transport().open_session()
File "/usr/lib/python2.7/site-packages/spur/ssh.py", line 179, in _get_ssh_transport
raise self._connection_error(error)
spur.ssh.ConnectionError: Error creating SSH connection
Original error: No existing session

Passing password for sudo commands

Hi Michael,
Thanks for the wonderful library. I wanted to use this library for running sudo commands, which prompt for passwords. As per documentation, there is no way to specify that. I went through the paramiko docs and they have a method to pass the password. I am going through the source ssh.py and trying to figure out where to modify. I would be great if u could help me on this. Thanks.

BSD is not compatible with license of Paramiko (LGPLv2)

Paramiko is licensed under LGPLv2 and seems to be very integrated into this module (not in a way that can be easily swapped out for another module) and this worries me because BSD is a much more liberal license than LGPLv2. Although it's never been taken to court whether dynamically importing modules that are licensed under LGPL* legally counts the same as linking I would not want you or people who use this module to be exposed to legal liability because of a license compatibility issue.

Could the license be changed to reflect this or is there some reason that I am missing for this not being the case?

Error reading SSH protocol banner[Errno 54]

I have been getting an Errno 54 when attempting to connect to a specific SSH server. I've been wondering if it has to do with a long greeting message that is printed when I login to that server. The code is fairly straightforward, and I have to tunnel through "server1.lab" to get to "server2.outside.com" because there is an allow list. I've gotten this to work with other outside servers using spur, but haven't been able to find any info on this particular error.

code:

import spur
shell = spur.SshShell(hostname="server1.lab", username="userA", password="passwordA")
with shell:
    result = shell.run(["hostname"])
    print result.output
    shell2 = spur.SshShell(hostname="server2.outside.com", username="userA", private_key_file="/home/userA/.ssh/id_rsa", missing_host_key=spur.ssh.MissingHostKey.accept)
    with shell2:
        result = shell2.run(["who"])
        print result.output

output:

server1.lab

No handlers could be found for logger "paramiko.transport"
Traceback (most recent call last):
  File "Untitled.py", line 13, in <module>
    result = shell2.run(["who"])
  File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 70, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 80, in spawn
    channel = self._get_ssh_transport().open_session()
  File "/usr/local/lib/python2.7/site-packages/spur/ssh.py", line 178, in _get_ssh_transport
    raise self._connection_error(error)
spur.ssh.ConnectionError: Error creating SSH connection
Original error: Error reading SSH protocol banner[Errno 54] Connection reset by peer

Test is failing

I'm getting:

+ nosetests-2.7 -e ssh
......................E.............
======================================================================
ERROR: tests.local_tests.LocalProcessTests.exception_message_shows_unicode_bytes
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
    self.test(*self.arg)
  File "/builddir/build/BUILD/spur.py-0.3.15/tests/process_test_set.py", line 22, in run_test
    test_func(shell)
  File "/builddir/build/BUILD/spur.py-0.3.15/tests/process_test_set.py", line 108, in exception_message_shows_unicode_bytes
    shell.run(["sh", "-c", _u("echo ‽; exit 1")])
  File "/builddir/build/BUILD/spur.py-0.3.15/spur/local.py", line 109, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File "/builddir/build/BUILD/spur.py-0.3.15/spur/local.py", line 66, in spawn
    **self._subprocess_args(command, *args, **kwargs)
  File "/usr/lib64/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
TypeError: execv() arg 2 must contain only strings

----------------------------------------------------------------------

No password authentication

Hello,

When I execute this:

shell = spur.SshShell(hostname='IP',
username='admin',
password='password')
shell.run('sh ver')

I always get :
spur.ssh.ConnectionError: Error creating SSH connection
Original error: Authentication failed.

From my router, I see public key authentication.

Are you sure to set up look_for_keys to false?

UnicodeDecodeError during install

Got the following error when trying to pip install:

Step 13 : RUN pip3 install -r requirements.txt
 ---> Running in 88308c270095
Collecting docker-py==1.7.0 (from -r requirements.txt (line 1))
  Downloading docker_py-1.7.0-py2.py3-none-any.whl
Collecting spur==0.3.15 (from -r requirements.txt (line 2))
  Downloading spur-0.3.15.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-build-t6r3jpgx/spur/setup.py", line 13, in <module>
        long_description=read("README.rst"),
      File "/tmp/pip-build-t6r3jpgx/spur/setup.py", line 7, in read
        return open(os.path.join(os.path.dirname(__file__), fname)).read()
      File "/usr/lib/python3.4/encodings/ascii.py", line 26, in decode
        return codecs.ascii_decode(input, self.errors)[0]
    UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 3190: ordinal not in range(128)

Perhaps we need to set the encoding when opening the file?

Can client.load_system_host_keys() be configurable?

Where I work there are many hosts that are running as fail over nodes and we consistently have hosts/key mismatch errors that we have to ignore to allow our scripts to work. These errors are causing our spur based scripts to fail prematurely in ssh.py here....
252 client.load_system_host_keys()
Can the load_system_host_keys() method be set as a configurable parameter?

Connection Refused - VirtualBox

I am trying to connect via ssh to a virtualbox. I have set up the vm to accept password and key authentication. The access is via port forwarding, e.g. localhost port 2222 to port 22 inside the guest machine.

Logging in via port 2222 works from bash, both with password and key file.

Using spur does not work. I am getting a "111: Connection refused".

I began using the original simple examples from the readme, then proceeded to try various things as mentioned in #2 .

Any further ideas?

Thank you for your time.

How do execute more than one command in one session?

I am trying to log on to machine. And I want to maintain the same session and execute multiple commands, one after another. Here's what I am trying to do in linux
cd /tmp/
java -jar
cd /tmp/results
ls -lrt

and from the examples you have mentioned, I am trying this:
shell = spur.SshShell(hostname="xx.xx.xxx.xxx",
username="xxxxx",
password="xxxxx",
shell_type=spur.ssh.ShellTypes.minimal,
missing_host_key=spur.ssh.MissingHostKey.accept)
with shell:
result = shell.run(["sh", "-c", "cd /tmp/"])
result = shell.run(["sh", "-c", "java -jar "])
result = shell.run(["sh", "-c", "cd /tmp/results"])
result = shell.run(["sh", "-c", "ls -lrt"])
print result.output

It is printing to all files in my directory when i log in. It is like I am logging in to shell everytime when i do shell.run. How can i just log on shell once, maintain a session and run multiple commands and close the session?

Allow to pass encoding when creating shell

The encoding parameter on run/spawn is nice, but it's a bit tedious to pass it to every run command.
It'd be nice to be able to pass it when creating the shell.

Something like that:

class SshShell(object):
    def __init__(self,
            hostname,
            username=None,
            password=None,
            port=None,
            private_key_file=None,
            connect_timeout=None,
            missing_host_key=None,
            shell_type=None,
            look_for_private_keys=True,
            load_system_host_keys=True,
            sock=None,
            encoding=None):

...

        self._encoding = encoding

    def spawn(self, command, *args, **kwargs):
        encoding = kwargs.pop("encoding", self._encoding)

We could then run:

import spur

shell = spur.SshShell(hostname="localhost", username="bob", password="password1", encoding="utf-8")

with shell:
    result = shell.run(["ls"])
    result = shell.run(["some_cmd"])

The above solution still allows to overwrite the encoding in the run command.

If you think it's a good idea, I can make a proper pull request.

Error 111 - Connection Refused

I am attempting to connect to an EC2 instance using a public key. I have never connected to this machine before so the host signature will not have been accepted yet.

Here is the error I am getting:

Traceback (most recent call last):
  File "deploy.py", line 206, in <module>
    downloadFiles(conn, instanceDNS)
  File "deploy.py", line 85, in downloadFiles
    shell.run(shlex.split('wget %s' % file))
  File "/home/tony/virtualEnvironments/aws/lib/python2.7/site-packages/spur/ssh.py", line 71, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File "/home/tony/virtualEnvironments/aws/lib/python2.7/site-packages/spur/ssh.py", line 80, in spawn
    channel = self._get_ssh_transport().open_session()
  File "/home/tony/virtualEnvironments/aws/lib/python2.7/site-packages/spur/ssh.py", line 176, in _get_ssh_transport
    raise self._connection_error(error)
spur.ssh.ConnectionError: Error creating SSH connection
Original error: [Errno 111] Connection refused

And here is the code that I am using:

shell = spur.SshShell(hostname=host, username=settings['ami_default_username'], private_key_file=settings['aws_ssh_key'], missing_host_key=spur.ssh.MissingHostKey.accept)                                                                                                                 

        for file in settings['files_to_download']:                                                                                          
            shell.run(shlex.split('wget %s' % file))

I have tried this manually as well using os.call and had no luck there either, so it might not be an issue with your library. I am able to connect when I type in the command manually though. Any ideas?

Add proxy command capabilities to SshShell

Hello,

This is sort a feature request / proposition.

When using paramiko's client.connect, you can can specify a sock=, this parameter can be passed an instance of paramiko.proxy.ProxyCommand instanciated with a proxy command such as...
"ssh -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null user@proxyname nc -q0 1.2.3.4 22"
Which would connect to 1.2.3.4 through the given proxy

So i would like to propose this change but wanted to know how you would see it implemented:

  • Ultra simple but very unituitive: spur.SshShell() takes a sock= param, keep it in self and pass it co client.connect in _connect_ssh
    • you would have to craft your proxy command yourself
    • could be useful for other use cases
  • Simple and more user-friendly : spur.SshShell() takes a proxy_command= param, keep it in self and makes a ProxyCommand to pass to client.connect in _connect_ssh
    • User needs understanding of proxy command (an example would be supplied) but won't have to directly refer to paramiko
  • More complex but most user-friendly i think: spur.SshShell() takes a proxy object that would define a user / pass / key for the proxy along with the port and some options, one would say you could even supply a SshShell as a proxy (value wise... maybe not implementation wise)
    • Could look like SshShell(username... proxy=SshShell(username...))
    • Or something along the lines of proxy=Proxy(username...) which would be a new object related only to proxying values.

What do you think?

cant connect to the adress

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname="10.32.19.206", port=22, username="root", password="Dell123")
stdin, stdout, stderr = ssh.exec_command("ls")
print type(stdin)

print stdout.readlines()
print 111111111111111111

import spur
shell = spur.SshShell(hostname="10.32.19.206", username="root", password="Dell123", port=22)
result = shell.run(["echo", "-n", "hello"])
print result.output # prints hello
print 222222222

and this is what I get.
<class 'paramiko.channel.ChannelFile'>
[u'anaconda-ks.cfg\n', u'Desktop\n', u'Documents\n', u'Downloads\n', u'Music\n', u'Pictures\n', u'Public\n', u'Templates\n', u'Videos\n']
111111111111111111

Traceback (most recent call last):
File "C:/Users/Demian_Kurejwowski/Desktop/monitor_machines/for_testing.py", line 29, in
result = shell.run(["echo", "-n", "hello"])
File "C:\Python27\lib\site-packages\spur\ssh.py", line 158, in run
return self.spawn(_args, *_kwargs).wait_for_result()
File "C:\Python27\lib\site-packages\spur\ssh.py", line 168, in spawn
channel = self._get_ssh_transport().open_session()
File "C:\Python27\lib\site-packages\spur\ssh.py", line 245, in _get_ssh_transport
raise self._connection_error(error)
spur.ssh.ConnectionError: Error creating SSH connection
Original error: Server '10.32.19.206' not found in known_hosts

Process finished with exit code 1

you know what I might be doing wrong? thanks.

Closing process stdin, stdout and stderr

Hi.

There seams to be no "official" way to close the standard input, output and error streams of a Spur process. A hack like

def close_std_streams(process):
    try:
        process._process_stdin.close() # Local
    except AttributeError:
        process._stdin.close() # SSH

    process._io._handlers[0]._file_in.close()
    process._io._handlers[1]._file_in.close()

appears to work, but is there a better way or should there be some method to do that?

Best regards
Niklas

Errors : Too many open files AND /dev/urandom (or equivalent) not found

Hi, first of all thanks for the lib it's very user friendly !

I've been using it in a monitoring application and i found these 2 errors (relevant end of the stack traces)

  File ".../deployment.py", line 63, in _is_command_success
    shell.run(["bash", "-c", command])
  File ".../lib/python2.7/site-packages/spur/local.py", line 114, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File ".../lib/python2.7/site-packages/spur/local.py", line 69, in spawn
    **self._subprocess_args(command, *args, **kwargs)
  File "/var/lib/jenkins/.pythonbrew/pythons/Python-2.7/lib/python2.7/subprocess.py", line 672, in __init__
    errread, errwrite)
  File "/var/lib/jenkins/.pythonbrew/pythons/Python-2.7/lib/python2.7/subprocess.py", line 1101, in _execute_child
    errpipe_read, errpipe_write = os.pipe()
OSError: [Errno 24] Too many open files

AND

  File ".../deployment.py", line 63, in _is_command_success
    shell.run(["bash", "-c", command])
  File ".../lib/python2.7/site-packages/spur/ssh.py", line 166, in run
    return self.spawn(*args, **kwargs).wait_for_result()
  File ".../lib/python2.7/site-packages/spur/ssh.py", line 178, in spawn
    channel = self._get_ssh_transport().open_session()
  File ".../lib/python2.7/site-packages/spur/ssh.py", line 266, in _get_ssh_transport
    return self._connect_ssh().get_transport()
  File ".../lib/python2.7/site-packages/spur/ssh.py", line 286, in _connect_ssh
    sock=self._sock
  File ".../lib/python2.7/site-packages/paramiko/client.py", line 338, in connect
    t.start_client(timeout=timeout)
  File ".../lib/python2.7/site-packages/paramiko/transport.py", line 499, in start_client
    raise e
NotImplementedError: /dev/urandom (or equivalent) not found

Environment info

These run on an old OS : Debian GNU/Linux 6.0.7 (squeeze)
The base python version of the os is Python 2.6.6 so we use pythonbrew to run 2.7.0
We use virtualenv 1.8.3
We have cryptography 1.4 (because we have OpenSSL 0.9.8o)

Situational information

These errors don't appear right away. The app was running fine doing stuff with RemoteShell and LocalShell and suddenly, the first stack trace happened once, and all subsequent calls to shell.run started giving the second stack trace, every time.

It happened after approximatively 4000 remote calls with RemoteShell and 1000 local calls with Localshell over 8 days.

Conclusion

This might be related to the old setup (that's most likely) but in any case it could help anyone figure out some problems i posted it here.

And to make this clear, i do use context managers when using the shells

with shell as s:
    s.run([...])

escape_sh() method generate nesting quotes string

escape_sh method generated nesting quotes string, but in some cases, the nesting qutoes command is not worked in embed linux system.

For instance,

escape_sh("help")
"'help'"
then channel.exec_command("'help'") will not work, the actual worked command should be channel.exec_command("help"), "help" instead of "'help'".

modified the method as followed, it worked in my case and tried with several scenarios with various linux system, it always worked fine.

def escape_sh(value):

  • return "'" + value.replace("'", "'''") + "'"
  • return value.replace("'", "'''")

Depends on termios, which is unix only

I tried to install this on Windows, which worked, but when importing, it failed due to missing termios. Termios is a unix only module.

EDIT: I tried to install this with Portable Python 2.7.5.1 on Windows

This should be noted in the readme and perhaps the setup.py should fail if termios is missing.

Pulling remote data locally

I'm having issues pulling remote data to the local computer. Do you have any samples for this? I tried to open the remote file, (which seems like it worked) but I'm not sure how to save it locally.

SSH Shell stuck in infinite while loop

Hi William,

I am having some odd issue where the code gets stuck in a infinite loop within _read_int_initialization_line(). I tried step through the program and it seems like variable line seems to empty all the time.

Sample Code:

with spur.LocalShell() as shell:
        result = shell.run(["echo", "hello"])
        print (result.output)
with spur.SshShell("*********", username="karthiks", password="********") as shell:
        result = shell.run(["echo 'hello'"])
        print (result.output)

The local shell works as expected, whereas the ssh shell gets stuck in infinite loop, any help is appreciated.

Thanks,
Karthik

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.