如何在没有提示符的情况下执行 ssh-keygen

我想使用 Centos7上的 shell 脚本自动生成一对 ssh 密钥,我已经试过了

yes "y" | ssh-keygen -t rsa
echo "\n\n\n" | ssh-keygen...
echo | ssh-keygen..

所有这些命令都不起作用,只需输入一个“ Enter”,shell 脚本就会停止在“ Enter passsphrase (空的没有密码)”上, 我只是想知道如何在 shell 中连续模拟多次“进入”。

如果有人能帮忙,非常感谢!

81871 次浏览

We need to accomplish two steps automatically:

  1. Enter a passphrase. Use the -N flag (void string for this example):

    ssh-keygen -t rsa -N ''

  2. Overwrite the key file:

Use -f to enter the path (in this example id_rsa) plus a here-string to answer yes to the following question:

ssh-keygen -q -t rsa -N '' -f ~/.ssh/id_rsa <<<y >/dev/null 2>&1

Or, under a bash like shell, If you certainly want to overwrite the previous one, use just a here-string to feed the command with all the need input:

ssh-keygen -q -t rsa -N '' <<< $'\ny' >/dev/null 2>&1

From ssh-keygen man page:

  -N new_passphrase provides the new passphrase.
-q                silence ssh-keygen.
-f filename       specifies the filename of the key file.

Step by step explanation

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/klashxx/.ssh/id_rsa):

1) To avoid entering the key use -f:

$ ssh-keygen -t rsa -f ~/.ssh/id_rsa
Generating public/private rsa key pair.
/home/klashxx/.ssh/id_rsa already exists.
Overwrite (y/n)?

ATTENTION: If you don't care about the RSA file name and certainly want to overwrite the previous one, check the instructions below point four.

2) Now we need to answer "y" automatically to the overwrite question (let's use a here-string for that job):

$ ssh-keygen -t rsa -f ~/.ssh/id_rsa <<< y
Generating public/private rsa key pair.
/home/klashxx/.ssh/id_rsa already exists.
Overwrite (y/n)? Enter passphrase (empty for no passphrase):

3) Finally we're going to use the -N flag to enter a void pass:

$ ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa <<< y
Generating public/private rsa key pair.
/home/klashxx/.ssh/id_rsa already exists.
Overwrite (y/n)? Your identification has been saved in /home/klashxx/.ssh/id_rsa.
Your public key has been saved in /home/klashxx/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Xo0t6caMB/8TSsigxfY28JIfqYjyqxRZrFrPncx5yiU klashxx@server
The key's randomart image is:
+---[RSA 2048]----+
|                 |
|  .              |
|   o .           |
|  +   *    =     |
| +.  + BSo= o    |
|...o.+o+XO...    |
|.. .o.E==+B. .   |
|o . ...=.o...    |
|.+o.  o     ..   |
+----[SHA256]-----+

4) Extra ball, cleanup the output, just check the return code:

$ ssh-keygen -q -t rsa -N '' -f ~/.ssh/id_rsa <<<y >/dev/null 2>&1
$ echo $?
0

An alternative path to overwrite the previous RSA file (no -f flag needed)

NOTE: Only bash like shells.

If you don't care about the RSA name and just want to overwrite it, we need to answer these two questions automatically:

  1. Enter file in which to save the key: /example/path/.ssh/id_rsa already exists.

  2. Overwrite (y/n)?

If we do this by hand, for the first question we just need to hit enter, and for the second, type y and press enter.

We can simulate these actions by using the following here-string:

$'\ny'

From the bash man page:

Words of the form $'string' are treated specially. The word expands to "string", with backslash-escaped characters replaced as specified by the ANSI C standard.

\n new line

So, if we use od to analyze our string:

cat - <<< $'\ny' | od -c
0000000  \n   y  \n

We see that we're getting just what we need to answer the questions.

Points 1 and 2 can be summarized into:

ssh-keygen -q -t rsa  <<< $'\ny'

And the final command will be:

$ ssh-keygen -q -t rsa -N '' <<< $'\ny' >/dev/null 2>&1
$ echo $?
0

Kudos

@lukasz-dynowski, @redochka, @mellow-yellow, @yeti and the rest of the folks in this thread.

If you don't want to prompt user for a file in which to save the key then, you can add file output flag -f to the command.

ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa

This way user will not be prompted for any input -unless id_rsa file(s) already exist.

For me, i had to use combination of both @Lukasz answer and @Juan one, when using in ssh command

ssh -p$SSH_PORT -q joker@$INSTANCE_IP 'yes y | ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa'

None of the answers do exactly what is expected. The wanted behavior: run ssh-keygen with default settings (like if we just spammed Enter) without ever prompting for input.

The command to run is:

yes '' | ssh-keygen -N '' > /dev/null

leave out the >/dev/null if you want to print output.

Explanation:
yes y spams 'y', which ssh-keygen takes literally and makes the keys in $PWD/y and $PWD/y.pub . yes '' spams empty lines (Enter) which is what we want. Specifying the file with -f ~/.ssh/id_rsa fails if .ssh directory doesn't exist. The -t rsa option is not required if rsa is the default type (we're spamming enter anyways). The passphrase is not read from stdin (which we're spamming enters on) but from the keyboard directly so nothing can intercept it. For this reason you need to specify -N '' for empty passphrase.

Inside my Dockerfile (From node:8.13.0), the following works nicely: yes 'y' | /usr/bin/ssh-keygen

More complete example:

yes 'y' | /usr/bin/ssh-keygen -q -N '' -t rsa -f /etc/ssh/ssh_host_rsa_key && \
yes 'y' | /usr/bin/ssh-keygen -q -N '' -t dsa -f /etc/ssh/ssh_host_dsa_key

Delete the current private key to prevent overwriting requests.

rm -f ~/.ssh/id_rsa && ssh-keygen -m PEM -t rsa -b 4096 -N '' -f ~/.ssh/id_rsa

The accepted answer still specifies a custom filename. This worked for me:

ssh-keygen -t rsa -b 4096 -N '' <<<$'\n'
  • -t rsa Specifies type of key to create (RSA).
  • -b 4096 Specifies the number of bits in the key to create (4096 bits).
  • -N '' Provides the passphrase (empty, in this case).
  • <<< Part of shell: "here string" to feed a string into the stdin of ssh-keygen.
  • $'\n' A newline (using $ to make the single-quoted string interpret special characters).

The command as given above creates a 4096-bit RSA key with an empty passphrase. It asks: Enter file in which to save the key (.../.ssh/id_rsa):, hence a newline (\n) is fed into the stdin, to automatically accept the default filename. If a key already exists, it will not do anything.

However, if you do wish to automatically overwrite an existing key without any prompt, then use (this is the real answer to the original question, but it's down here to prevent unintended overwriting for people who copy&paste without reading):

ssh-keygen -t rsa -b 4096 -N '' <<<$'\ny\n'

To silence ssh-keygen stdout, either add the -q (quiet) option or >/dev/null:

ssh-keygen -t rsa -b 4096 -N '' <<<$'\n' >/dev/null

From the accepted answer above, I created my own version

ssh-keygen -q -t rsa -N '' -f ~/.ssh/id_rsa <</dev/null 2>&1 && cat ~/.ssh/id_rsa.pub | pbcopy

It will automatically create the ssh key and copy the public key to the clipboard --> which allows me to paste to github, azure dev...