6

If I have a linux command that prompts for 2 or more input, how can these inputs be passed to the prompt by defining it in the command line? Is there something you can add behind the command to do this?

In the example below, how can you run the command and pass it the username and password without having to type it in when the system asks for them?

Example command that asks for username and password

git clone https://github.com/username/repo.git 

Just an example, please don't suggest doing the git clone using ssh instead of http, or that its insecure to expose the password in the command

Nyxynyx
  • 61,411
  • 155
  • 482
  • 830
  • 6
    **man expect** ... if it's not installed: **sudo apt-get install expect** – tink Apr 16 '13 at 00:57
  • Note that the specific command is relevant because some use standard input and output (which usually can be redirected by the usual shell means) while others, like ssh used by git, uses the terminal. I'm almost sure there are "terminals" conceived to support your usage (and maybe expect can do that) but it's always a bad crutch. Which is the reason that almost all particular interactive programs (e.g., vi) have non-interactive counterparts (e.g., sed) and people answer with "but don't do that" in every particular case (like git). – Peter - Reinstate Monica Dec 16 '21 at 08:05
  • Ah, [here on superuser](https://superuser.com/questions/1610065/failed-attempt-to-expect-and-send-in-an-expect-script-in-mingw) is an instruction how to use expect for that. Ending, predictably, in "but don't do that" ;-). So this is a dup but on another SE. – Peter - Reinstate Monica Dec 16 '21 at 08:10

7 Answers7

4

The "expect" package is built for this kind of thing. If you install it, check out "autoexpect".

Example:

autoexpect
# Output: autoexpect started, file is script.exp

# Login with user/pass with ssh - just to test
ssh -o PubkeyAuthentication=no myuser@myhost
<type-password>
<command>
<command>
exit

# Now exit once more to exit autoexpect
# Output: autoexpect done, file is script.exp

Next thing is to edit script.exp and clean it up. There is loads of documentation on this.

sastorsl
  • 2,015
  • 1
  • 16
  • 17
  • Hmm... A comment to [this answer](https://stackoverflow.com/questions/6531241/how-to-use-expect-and-git-clone) seems to suggest that expect wouldn't work here because ssh uses the terminal device instead of stdin/stdout. I'm not sure expect can do that. It may though because those are the interesting cases. Can you provide an example? – Peter - Reinstate Monica Dec 16 '21 at 08:03
3

I want the bounty, and I can't close as dup because the answer is on a different SE.

Quoting the answer on superuser:

Use the program expect which has been conceived for exactly your needs which were felt already by users in a land before our time, given that its man page states:

Connect to another network or BBS (e.g., MCI Mail, CompuServe).

Compuserve, was that before or after the French Revolution? Anyway.

spawn "git clone ssh://git@domain.com/myproject.git"
expect "Enter passphrase for key..." { send "myPassword\r" }
read -p "enter..."

Perhaps the last line is superfluous.

Ceterum censeo: Don't do that.

Peter - Reinstate Monica
  • 15,048
  • 4
  • 37
  • 62
2

NOTE: Git requires you to use git token instead of password.

empty is an utility that provides a simple interface to execute and/or interact with processes under pseudo-terminal sessions.

This tool is definitely useful in programming of shell scripts that are sed to communicate with interactive programs like telnet or FTP.

In some cases empty can be a substitution for TCL/expect or other similar programming tools.

Copy the bellow code into your script file.

Make it executable and run the script by providing the following argument from the command line (as you asked for it):

  • Git repo URI (as the first argument)
  • Git username (as the second argument)
  • Git user token (as the third argument)

Example:

Assuming your script file name is: git_clone.sh:

./git_clone.sh  <GIT_REPO_URI>  <GIT_USERNAME>  <GIT_USER_TOKEN>
#!/bin/bash
git_repo="${1}"
git_user="${2}"
git_token="${3}"

empty -f -i in.fifo -o out.fifo -pempty.pid  git clone  

empty -w -i out.fifo -o in.fifo sername  "${git_user}\n"
empty -w -i out.fifo -o in.fifo assword  "${git_token}\n"

exit 0

For more details about empty refer to its manual: http://manpages.ubuntu.com/manpages/bionic/man1/empty.1.html

Note: empty command needs to be available by installing empty-expect package.

To install on Ubuntu 18.04 or 16.04 you can run:

add-apt-repository "deb http://archive.ubuntu.com/ubuntu $(lsb_release -sc) universe"
apt update;
apt install -y empty-expect

### Update: To install empty-expect package in Ubuntu 20.04 you may use the Ubuntu 18.04 (bionic) universe repository by running the following commands:

echo 'deb http://archive.ubuntu.com/ubuntu bionic universe' > /etc/apt/sources.list.d/bionic-universe.list
apt update
apt install -y empty-expect
Vab
  • 412
  • 1
  • 11
  • `empty: command not found` Why am I getting this error? – Sai Suman Chitturi Dec 22 '21 at 13:08
  • @ChitturiSaiSuman, please make sure that you have empty-expect package installed. Example how to install on Ubuntu-based distributions, run: sudo apt update; sudo apt install empty-expect – Vab Dec 23 '21 at 07:59
  • Hi, it seems like the 'empty-expect' package is not available on `Ubuntu 20.04 LTS` (Ubuntu Focal). – Sai Suman Chitturi Dec 24 '21 at 12:04
  • @ChitturiSaiSauman, I don't have Ubuntu 20.04 but I'd suggest the following: google it, and share the output of what you get when you run the commands in my previous comment. Thank you. – Vab Dec 25 '21 at 20:15
  • ``` sudo apt install -y empty-expect Reading package lists... Done Building dependency tree Reading state information... Done E: Unable to locate package empty-expect ``` – Sai Suman Chitturi Dec 26 '21 at 12:39
  • @ChitturiSaiSuman I've tested and updated my answer. To install `empty-expect` package in ubuntu 20.04 you may use the ubuntu 18.04 (bionic) `universe` repository. Please vote up my answer if you find it usefull. – Vab Dec 27 '21 at 10:37
1

Under , you could use script

script will produce a tty you could interact with under , using coproc. This could be done without de need of expect:

NAME
      script - make typescript of terminal session

SYNOPSIS
      script [options] [file]

DESCRIPTION
      script  makes  a  typescript  of everything on your terminal session.
      The terminal data are stored in raw form to the log file and information
      about timing to another (optional) structured log file. The timing
      log file is necessary to replay the session later by scriptreplay(1) and to
      store additional information about the session.

Demo

coproc script -f /dev/null

Could return:

[1] 2103233

This initiate a subshel, you coul interact with,

while read -t 0 -u ${COPROC[0]};do
    read -t .02 -ru ${COPROC[0]} line
    echo "$line"
done

should produce something like:

Script started, output log file is 'typescript'.
user@hostname:~$

Then

echo >&${COPROC[1]} ssh user@target
while [ ! "$line" ] || [ "${line//*password*}" ];do
    read -t .02 -ru ${COPROC[0]} line
    echo "$line"
done
echo >&${COPROC[1]} TheStrongPasswordInClear
while [ ! "$line" ] || [ "${line//*\$*}" ];do
        read -t .02 -ru ${COPROC[0]} line
    echo "$line"
done

There, you could see a lot of lines like

ssh user@target
user@target's password:

Linux target 5.00.0-0-amd64 # Distro ...
issue.net content...
Last login: Sun Dec 19 12:23:37 2021 from somewhere

user@target:~$ 

From there, you could:

getres() {
    while read -t 0 -u ${COPROC[0]};do
        read -t .02 -ru ${COPROC[0]} line
        echo "$line"
    done
}

echo >&${COPROC[1]} uptime
getres
uptime
12:38:38 up 21 days,  3:52, 122 users,  load average: 3.20, 2.19, 1.59

And finaly

echo >&${COPROC[1]} exit  
getres 
exit
logout
Connection to target closed.

Full executable script

This run under bash 5.1.4(1)-release, on GNU/Debian Linux 11.2:

#!/bin/bash
line='' Debug=false

exp1() { # Collect input by bytes, until expected string (1st arg)
    local char attended="*${1}"
    line=
    IFS= read -d '' -ru "${COPROC[0]}" -t 2 -n 1 line
    while IFS= read -d '' -ru "${COPROC[0]}" -t .02 -n 1 char;do
        line+="$char"
        case "$line" in
            *$1 ) $Debug && echo "GOOD ${line@A} match ${attended@A}"
                  return 0;;
        esac
    done
    $Debug && echo "BAD: ${line@A}"
    return 1
}
expect() { # expect <Expected String after> <Command> [switches] [args]
    local expectStr="$1" maxErr=5
    shift
    [ "$1" ] && echo >&"${COPROC[1]}" "$@"
    while ! exp1 "${expectStr}" && ((maxErr--));do sleep .2;done
}
getAns() { # getAns <ResultVar> <Command> [switches] [args]
    local -n res=$1
    res=''
    shift
    local req="$*" maxErr=5
    echo >&"${COPROC[1]}" "$req"
    exp1 "$req"$'\r\n'
    while ! exp1 "$ " && ((maxErr--));do res+="$line" ;sleep .2 ;done
    res+="${line%$'\r\n'*}"
}
read -rp target:\  target
read -rsp password:\  pass
echo "${pass//?/*}"

coproc TERM=none script -f /dev/null
IFS= read -ru "${COPROC[0]}" line &&
    $Debug && echo "1 >>> $line <<<"

expect '$ '
expect 'password: ' ssh "$target"
expect '$ ' "$pass"

getAns ut uptime
# shellcheck disable=SC2154 # referenced but not assigned (ut ??)
echo "${ut@A}"

expect '$ '  exit

Run sample:

target: user@target
password: ************
ut=' 11:06:20 up 5 days, 2:19, 22 users, load average: 0.74, 1.13, 1.27'

You may found this script on my site: expectScr.sh, or expectScr.sh.txt, ready to be sourced.

F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
  • Answer edited: Here is now a full executable script! On my site: [expectScr.sh](https://f-hauri.ch/vrac/expectScr.sh), or [expectScr.sh.txt](https://f-hauri.ch/vrac/expectScr.sh.txt). – F. Hauri - Give Up GitHub Dec 22 '21 at 12:03
0

Perhaps this

{
  echo user
  echo pass
} | git clone https://github.com/username/repo.git

ref

Zombo
  • 1
  • 62
  • 391
  • 407
  • 2
    This will work if `git` reads the password from stdin, but not if it reads it from `/dev/tty` (as many password-prompting applications do). I don't know offhand how `git` works in this regard. – Barmar Apr 16 '13 at 01:07
0

Depending on why you want to do this, you may want to explore ways to use github repositories without passwords:

https://help.github.com/articles/managing-deploy-keys

Cargo23
  • 3,064
  • 16
  • 25
0

Don't know have you tried this or not. But this is useful in case we execute any sudo cmd and needs to enter a password. You can try this in your case.

But I think you have to provide a username at least.

For example :

sudo -S <<< "password" sudo yum -y update 

In your case, it should be like :

sudo -S <<< {password} git clone https://github.com/{username}/repo.git
Sachin
  • 1,460
  • 17
  • 24