BASH - Assign SSH output to variable - bash

I've read all the threads that I could find regarding this issue that I am having, however I have not yet found a solution to my problem.
First let me say that I am currently attempting to do this work in a very restrictive environment so I do not have the option of messing with configurations or any other admin type functions.
code:
ssh -t username#host "sudo -u user hadoop fs -ls /"
running this returns the output that I am looking for, however the next line will hang and does not assign the output to the variable:
output=$(ssh -t username#host "sudo -u user hadoop fs -ls")
I have attempted any and all variations of this line that I could find. If I do an echo of the variable it just spits out a blank line. The reason for the -t option is becuase without it I was getting an error along the lines of:
sudo: no tty present and no askpass program specified
sudo: pam_authenticate: Conversation error
I really don't have any contingency plans if I can't get this single line to work, so if you can help, it would be greatly appreciated.

Please give this a shot. I was able to do it at least 10 times in a row
output=$(sshpass -f <(printf '%s\n' $password) ssh user:#host "sudo ls");
echo $output;
This command is using sshpass to pass the password non interactively to the ssh command.

Related

How can i redirect unwanted output on bash login over ssh?

I've got a script, that will use ssh to login to another machine and run a script there. My local script will redirect all the output to a file. It works fine in most cases, but on certain remote machines, i am capturing output that i don't want, and it looks like it's coming from stderr. Maybe because of the way bash is processing entries in its start-up files, but this is just speculation.
Here is an example of some unwanted lines that end up in my file.
which: no node in (/usr/local/bin:/bin:/usr/bin)
stty: standard input: Invalid argument
My current method is to just strip the predictable output that i don't want, but it feels like bad practice.
How can i capture output from only my script?
Here's the line that runs the remote script.
ssh -p 22 -tq user#centos-server "/path/to/script.sh" > capture
The ssh uses authorized_keys.
Edit: In the meantime, i'm going to work on directing the output from my script on machine B to a file and then copying it to A via scp and deleting it on B. But i would really like to be able to suppress the output completely, because when i run the script on machine A, it makes the output difficult to read.
To build on your comment on Raman's answer. Have you tried supressing .bashrc and .bash_profile as shown below?
ssh -p 22 -tq user#centos-server "bash --norc --noprofile /path/to/script.sh" > capture
If rc-files is the problem on some servers you should try and fix the broken rc-files instead of your script/invocation since it'll affect all (non-interactive) logins.
Try running ssh user#host 'grep -ls "which node" .*' on all your servers to find if they have "which node" in any dotfiles as indicated by your error message.
Another thing to look out for is your shebang. You tag this as bash and write CentOS but on a Debian/Ubuntu server #!/bin/sh gives you dash instead of (sh-compatible) bash.
YOu can redirect stdout (2) to /dev/null and redirect the rest to the log fole as follows:
ssh -p 22 -tq user#centos-server bash -c "/path/to/script.sh" 2>/dev/null >> capture

Pass password to sudo for command that expects input

I am trying to create a Shell script and (to avoid typing, furthermore ignoring security related issues for now) want to directly pass the password to the "sudo" command, e.g.,
pword="mypassword"
echo $pword | sudo -S whoami
This works just fine. But now when the command itself expects an input, this method seems to fail, e.g.,
echo $pword | sudo -S cat<<<"Hello"
This would lead to an 'incorrect password' error. Currently, my solution is to run a "dummy command" like in example one first, and use the fact that for the second command the system does not prompt for a password again. However, does anyone know a better solution to get it to work?
You can defer the activation of the "here document" (the <<< construct) by doing something like this:
echo $pw | sudo -S sh -c ' cat <<<"Hello" '
A better solution is to use sudo -A instead of sudo -S, after first defining a $SUDO_ASKPASS environment variable to refer to a program that will emit your password. Then you won't have to worry about competing for stdin with the rest of the command line. You should create that askpass program (it can be a shell script) to be readable, writable and executable only by yourself so that your password will be securely hidden inside the program.
The -v flag of sudo is also useful if you have just entered your password for the SSH connection, -v updates the cache and doesn't ask for a password again:
sudo -v -u UserName && bash -c 'cat <<<"Hello"'

Linux expect script

I've spent the better part of 8 hours trying to figure this out with google, so I hope this warrants asking here.
I need a script that will auto-enter a password when I try to connect from my lubuntu image in vmware to a physical device connected by usb.
I've tried at least 50 different scripts I've found online, but none of them worked (or even recognised spawn as a command)
This is my script:
#!/usr/expect
spawn CPY2T_old.sh
expect "root#10.9.8.2's password:"
send "ThePassword"
expect eof
The contents of CPY2T_old.sh is
#!/bin/bash
cd hellolinux/src/Exercise$1
scp $2 root#10.9.8.2:
The above bash script works fine, but I have to enter the password, which is what I'm trying to avoid in the first place. The expect script gives the following when I execute in cmd:
spawn: command not found
couldn't read file "root#10.9.8.2's password:": no such file or directory
The program 'send' can be found in the following packages:
* mailutils-mh
* nmh
Try: sudo apt-get install <selected package>
couldn't read file "eof": no such file or directory
I've downloaded mailutils and nmh at least a dozen times by now as well. Elsewhere I read I need to #echo off at the top, but this command isn't recognised and gives an error.
EDIT: I can't do passwordless ssh to this device, so please don't suggest it.
I see 2 errors: first
#!/usr/expect
You want
#!/usr/bin/expect
That should have caused an error: how are you launching your expect script?
Second
send "ThePassword"
You forgot to hit enter
send "ThePassword\r"
#!/usr/bin/expect
set timeout 60
spawn ssh user#ip
expect "user#ip's password: "
send "Password\r"
interact
Note:Please be sure of all scripts are executable with command $ chmod +x #file_name or $ chmod 700 #file_name.
\r to execute
Github link:https://github.com/asarari207/Lunix_sh

SMB Client Commands Through Shell Script

I have a shell script, which I am using to access the SMB Client:
#!/bin/bash
cd /home/username
smbclient //link/to/server$ password -W domain -U username
recurse
prompt
mput baclupfiles
exit
Right now, the script runs, accesses the server, and then asks for a manual input of the commands.
Can someone show me how to get the commands recurse, prompt, mput baclupfiles and exit commands to be run by the shell script please?
I worked out a solution to this, and sharing for future references.
#!/bin/bash
cd /home/username
smbclient //link/to/server$ password -W domain -U username << SMBCLIENTCOMMANDS
recurse
prompt
mput backupfiles
exit
SMBCLIENTCOMMANDS
This will enter the commands between the two SMBCLIENTCOMMANDS statements into the smb terminal.
smbclient accepts the -c flag for this purpose.
-c|--command command string
command string is a semicolon-separated list of commands to be executed instead of
prompting from stdin.
-N is implied by -c.
This is particularly useful in scripts and for printing stdin to the server, e.g.
-c 'print -'.
For instance, you might run
$ smbclient -N \\\\Remote\\archive -c 'put /results/test-20170504.xz test-20170504.xz'
smbclient disconnects when it is finished executing the commands.
smbclient //link/to/server$ password -W domain -U username -c "recurse;prompt;mput backupfiles"
I would comment to Calchas's answer which is the correct approach-but did not directly answer OP's question-but I am new and don't have the reputation to comment.
Note that the -c listed above is semicolon separated list of commands (as documented in other answers), thus adding recurse and prompt enables the mput to copy without prompting.
You may also consider using the -A flag to use a file (or a command that decrypts a file to pass to -A) to fully automate this script
smbclient //link/to/server$ password -A ~/.smbcred -c "recurse;prompt;mput backupfiles"
Where the file format is:
username = <username>
password = <password>
domain = <domain>
workgroup = <workgroup>
workgroup is optional, as is domain, but usually needed if not using a domain\username formatted username.
I suspect this post is WAY too late to be useful to this particular need, but maybe useful to other searchers, since this thread lead me to the more elegant answer through -c and semicolons.
I would take a different approach using autofs with smb. Then you can eliminate the smbclient/ftp like approach and refactor your shell script to use other functions like rsync to move your files around. This way your credentials aren't stored in the script itself as well. You can bury them somewhere on your fs and make it read only by root an no one else.

Remote sudo, execute a command and write output in local terminal

What I try to do, I connect to a remote server as a normal user with sudo right, then sudo to root, and execute a command & see output in my local terminal. I wrote a small script like this:
#!/bin/bash
my_argument=$1
ssh -t username#hostname 'sudo su -; /path_to_my_script $1'
I type the password twice (one for ssh, the other for sudo), but I see nothing in my local terminal, and script looks terminated in remote host. I believe second problem could be resolved by using exit, but I am a little bit confused how I can get this output to my local terminal.
Thanks
String inside '' is taken literally. So, you are passing the dollar sign and 1 as a parameter to the script. If you want the string to be interpreted, place it inside "", like:
ssh -t username#hostname "sudo /path_to_my_script $1"

Resources