stdin from heredoc not printing to screen? - bash

I have a program that interactively logins a user. I used the heredoc to automate the process.
./login <<EOF
user1#test.com
password
EOF
I was expecting the output would be something like this. This is what it displays when I run the program without the heredoc and type in username and password myself.
$ ./login
Enter your email: user1#test.com
Enter your password: password
Successfully logged in.
However, I only see this.
$ ./login
Enter your email:
Enter your password:
Successfully logged in.
As you can see, all of the heredoc inputs are not printed out, even though the program seems to be getting the stdin correctly. What's the reason for this? It would be great if I could still see those inputs to help me debug problems. Thanks.

The login program disables the local echo (see https://man7.org/linux/man-pages/man1/stty.1.html).
Update
If the login program is writen by you, then is much easier, just echo the values after reading them

ECHO is a feature of the tty when users manually type chars to the tty. Your ./login << ... does not get input from the tty so the heredoc is not echoed. It's just like, for example,
grep something < /some/file
where you don't want it to echo the whole file's data.

Related

SSH/Expect How does "expect" work in expect shell script?

I try to use ssh remote login with expect. It works, but some outputs are not expected and I do not know why. This is my shell script:
#!/bin/sh
expect -c ' spawn ssh USER#ADDRESS ;
expect "?assword:" ;
send "MyPassword\r" ;
expect "?" ;
send "logout\r" ;
interact'
This is the output in my MacOS terminal:
ip87-114:Downloads tasiyuchien$ ./test.sh
spawn ssh USER#ADDRESS
Password:
logout
Last login: Tue Sep 13 18:17:21 2022 from ADDRESS
xdn42o221:~ USER$ logout
Connection to ADDRESS closed.
ip87-114:Downloads tasiyuchien$
The first question is why there is a "logout" output after "Password:"? Isn't the question mark represents any single character? Is there any implicit output or pattern I don't see cause I see nothing after "Password:". (Also strangely, when I replace "?" as "*", nothing will be output after "Password:" and the automatic logout also failed.) The same question can be asked when I login, cause I also see nothing but the "logout" is output.
The second question is why are there two "logout" outputted, I thought the except argument can be reused only if "except continue" is added.
Can anyone explain to me what's happening. Thanks!
As part of the login process, after the Password: prompt is shown, you enter your password and hit Enter, then the login process prints a newline. This newline is the character matched by "?".
Changing "?" to "*" works better: the asterisk is more greedy probably. Instead of matching exactly one character, it matches one or more characters, so it will try to collect as many as possible.
Why two "logout"s appear? I don't know. Perhaps your shell re-prints user input after displaying your prompt..

Bash how to input data on system prompt

How do I enter data on system prompts in bash?
Let's say in a bash script, I ssh into a PC.
How do I enter the credentials.
It may not be even credentials. Something as simple as "do you want to proceed (yes/no):"
How do you enter either yes or no?
I tried echo "yes", but doesn't work. I don't even see "yes" being printed on the screen.
Normally you'd just use echo or cat as in
$ touch file
$ echo yes | rm -i file
rm: remove regular file ‘tmp.c’?
But note that some programs may behave differently if stdin is non-interactive (i.e. you redirect stdin from echo) and some programs (e.g. ssh) read input directly from tty so redirecting stdin will not help. In such cases there are usually program-specific command-line switches to provide input data by other means.

BASH scripting for username/password constructs

I want to write a simple bash script using ncat to open a connection to a ISP and its port.
The first command would be:
nc address port
Upon doing this, I am prompted first to provide a username. I must hit ENTER, and then I will be prompted to provide a password and then I must hit ENTER again.
After this, I want to open a Terminal process window. Can anyone point me to sufficient resources for this type of scripting?
I know the username and password already, but I'm not too sure how to work around the fact that I must provide it and then hit enter. I'm also unsure how to open a new Terminal proceses.
Thanks in advance!
Check out expect script
Expect
Example:
# Assume $remote_server, $my_user_id, $my_password, and $my_command were read in earlier
# in the script.
# Open a telnet session to a remote server, and wait for a username prompt.
spawn telnet $remote_server
expect "username:"
# Send the username, and then wait for a password prompt.
send "$my_user_id\r"
expect "password:"
# Send the password, and then wait for a shell prompt.
send "$my_password\r"
expect "%"
# Send the prebuilt command, and then wait for another shell prompt.
send "$my_command\r"
expect "%"
# Capture the results of the command into a variable. This can be displayed, or written to disk.
set results $expect_out(buffer)
# Exit the telnet session, and wait for a special end-of-file character.
send "exit\r"
expect eof
The secret lies in the HEREDOC
You can solve this problem with something akin to:
$ command-that-needs-input <<EOF
authenticate here
issue a command
issue another command
EOF
Look at the link I provided for here documents - it includes support for variable substitution and lots of other useful things. Enjoy!

using grep in a script which prompt user for input

I have written one shell script which ask for some username and password from standart input.
Once username and password is typed there is a output depending upon the parameters passed in the script.
Say my script name is XYZ.ksh.
Now my problem is that users of these script want to use want to use this script in conjugation with other shell commands like grep, less, more, wc etc.
Normally yes they can use
XYZ.ksh | grep abc
But in my case since XYZ is prompting for username and password we are not able to use "|" in front of that. It blocks forever.
I just wanted to know how can I implement the functinality.
What I tried
I tried taking input of "more commands " from user where user types things like "| grep abc"
but when i used this input in my script it did not work.
Use <<< like this:
XYZ.ksh <<< "your inputs" | grep abc
In your script you can test to see if stdout is connected to a terminal with:
if [[ -t 1 ]]
That way you can supress the prompt if the output is not going to the console.
Alternatively, with your "more commands" solution, run the command connected to a named pipe.
There are multiple solutions commonly used for this kind of problem but none of them is perfect :
Read password from standard input. It makes it really hard to use the script in pipes. This method is used by commands that deal with changing passwords : passwd, smbpasswd
Provide username and password in the command line parameters. This solution is good for using the script in pipes, but command line can be viewed by anyone, using ps -ef for exemple. This is used by mysql, htpasswd, sqlplus, ...
Store username and password unencrypted in a file in user's home directory. This solution is good for using the script in pipes, but the script must check if the file is visible or modifiable by other users. This is used by mysql
Store private key in local file and public key in distant file, as used by SSH. You must have a good encryption knowledge to do this correctly (or rely on SSH), but it's excellent for use in pipes, even creating pipes accross different machines !
Don't deal with passwords, and assume that if a user is logged in in the system, he has the right to run the program. You may give execute privilege only to one group to filter who can use the program. This is used by sqlplus from Oracle, VirtualBox, games on some Linux distributions, ...
My preferred solution would be the last, as the system is certainly better than any program I could write with regard to security.
If the password is used to login to some other service, then I would probably go for the private file containing the password.
One less-than-optimal possibility is to display the prompt to stderr instead of stdout.
echo -n "Username:" >/dev/stderr
A better solution would be to check stdin of the shell. If it's a terminal, then open it for writing and redirect to that file. Unfortunately, I'm not sure how to do that in bash or ksh; perhaps something like
echo -n "Username:" >/dev/tty
You can use (I assume you are reading username and password in your script with read)
(
read -p "user:" USER
read -p "pass:" PASS
) < /dev/tty > /dev/tty
and you'll be able to run
$ cmd | XYZ.ksh
However, I agree with other answers: just don't ask for user and password and give the correct permissions to the script to allow access.

Run a Bash Script automatically upon login

I wrote a script that sends the date and username of the person who logs in to a log file to keep a record of who has logged in. I am wondering how can you set this script to execute automatically when a user logs in rather than have to manually run it in the terminal. NOTE: the USERNAME is the current user that is logged in.
my code:
#!/bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/USERNAME/boot.log
A more elegant way to solve this problem is to read from log files that are already being written and cannot be changed by the user. No one could say it better than Bjørne Malmanger's in his answer:
I wouldn't trust the user to GIVE you the information. As root you
TAKE it ;-)
A nice way to do this is the last command, which is great because it neatly displays all logins: Graphical, console and SSH.
last
A less elegant but still secure way is to do a grep on /var/log/auth.log. On my Gnome/Ubuntu system I can use this to track graphical logins:
grep "session opened for user USERNAME"
The right pattern for your machine needs to be found for each login type: graphical, console and SSH. This is cumbersome, but you might need to do it if you need information that goes further back than last reaches.
To directly answer your question:
You can modify the script like this to get the username
#!bin/bash
printf "$(date) $HOSTNAME booted!\n" >> /home/$(whoami)/boot.log
And add this line to /etc/profile
. /path/to/script.sh
This is not secure though because the user will be able to edit his own log
Why don't you use the last command?
I wouldn't trust the user to GIVE you the information. As root you TAKE it ;-)
Put it in ~/.bash_profile. It will be run each time they log in.
More information is available at the women's rights page (i.e. man bash).

Resources