在通过rebar3 shell运行的Erlang应用中获取隐藏用户输入
Erlang中SSH连接的密码输入与密钥认证方案
1. 实现隐藏式密码输入(交互场景)
你之前尝试的io系列函数默认会回显输入内容,而os:cmd("read -s pass")会启动独立子shell,和Erlang进程的终端环境分离,导致无法捕获输入进而阻塞。正确的做法是直接操作Erlang终端的回显选项:
get_password() -> IoDevice = standard_io, {ok, OrigOpts} = io:getopts(IoDevice), try % 关闭终端回显 ok = io:setopts(IoDevice, [{echo, false}]), % 提示用户输入并读取内容 {ok, Password} = io:get_line(IoDevice, "Enter password: "), % 手动输出换行(关闭回显后输入的换行不会显示) io:nl(), % 去掉输入末尾的换行符 string:trim(Password) after % 无论成功失败,都恢复终端原配置,避免影响后续操作 ok = io:setopts(IoDevice, OrigOpts) end.
调用这个函数后,终端会提示输入密码,输入过程中字符不会显示,读取完成后自动恢复终端回显。
2. 使用SSH密钥认证(非交互/更安全场景)
如果你的应用需要避免交互输入(比如后台运行),或者追求更高安全性,推荐使用SSH密钥对认证,完全替代密码输入:
步骤1:生成SSH密钥对
在终端执行以下命令生成密钥对(推荐使用ed25519算法):
ssh-keygen -t ed25519
按提示操作,默认会在~/.ssh目录下生成私钥id_ed25519和公钥id_ed25519.pub。
步骤2:配置服务器授权
将本地生成的公钥内容复制到目标服务器的~/.ssh/authorized_keys文件中,确保文件权限为600,目录~/.ssh权限为700。
步骤3:Erlang代码实现密钥认证
connect_with_ssh_key() -> FixedUsername = "your_hardcoded_username", TargetHost = "your_target_host", SshPort = 22, ConnOpts = [ {user, FixedUsername}, % 指定SSH配置目录,自动读取私钥文件 {user_dir, filename:basedir(user_config, ".ssh")}, % 生产环境建议关闭此选项,手动管理known_hosts文件 {silently_accept_hosts, true} ], case ssh:connect(TargetHost, SshPort, ConnOpts) of {ok, ConnRef} -> io:format("SSH connection established~n"), ConnRef; {error, Reason} -> io:format("Connection failed: ~p~n", [Reason]), error(Reason) end.
这种方式无需输入密码,Erlang的ssh模块会自动读取私钥完成认证,适合非交互场景的应用。
内容的提问来源于stack exchange,提问作者halfway258
相关产品推荐
相关产品推荐

