0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

weztermで自動ログイン

0
Last updated at Posted at 2026-06-02

weztermで自動ログイン機能を作る

まえふり

複数のPCを跨った処理を無人で実行したい場合、SSHを利用したいのだけれど、今どきのLinuxはセキリティ問題のためか、パスワード入力に関しては自動化できないようになっている。

こんな時でも、両側のPCの管理者権限を持っているのならば、パスワードを廃止し、鍵ファイルのみで運用することで自動化を達成するべきなんだろうね。

でも、そうはいかない場合は無理矢理やっちゃうか。

基本

動作条件

  • OSはLinuxまたはWindows。おそらくはbsdやMacOSでも。
  • 接続相手はOpenSSHサーバーで、クライアントもOpenSSHクライアントであること。
    (パスワードプロンプトのパターンを利用してハンドシェークしているので、そこを修正して対応するのならば、OpenSSHである必要はない)
  • ターミナルソフトであるweztermの自動入力機能を使うのでweztermが必要。
  • なにかしらのスクリプト言語、ここではRubyを使用する。

シナリオ

  1. sshクライアントを起動する。
  2. 並行ジョブでパスワードプロンプトを待って、パスワードを送信する

手抜きコードで動作説明

ほんとに必要最低限、低負荷のLAN内サーバーだと5行かそこらの記述で動く。
手抜きポイントは「sleep 1」で、
確実に1秒待てばパスワードプロンプトが来るならこれで問題ない。

Thread.new() { 
  sleep 1
  open("|wezterm cli send-text", 'w') { |out|
    out.print "パスーワード\r"
  }
}

system "ssh ユーザー@ホスト"

本番

手抜きを改めてハンドシェークする

手抜きした「sleep」の部分をちゃんとパスワードプロンプトを待つようにするには、
weztermの機能を使ってテキスト形式のスクリーンショットを取って、
末尾に「ユーザーID@ホスト名's password:」が現れるまで待つように書き換える。
スクリーンショットを取るコマンドは「wezterm cli get-text」である。

待ち時間はサーバーの混雑具合によってまちまちで、
軽いと瞬時だけれど混雑サーバーだと数時間かかる場合もあるので、
試行回数が増えるにしたがって動作間隔を開けるようにしておく。

  pttn = /#{$USER}@#{$HOST}'s password:$/
  secs = 1
  begin
    sleep secs
    secs = (secs < 64) ? (secs * 2) : 64
    lines = open("|wezterm cli get-text").read.chomp.split(/\n/).map { |s|
      s = s.strip
    }
    lines.delete('')
  end until (lines.size > 0) && (lines[lines.size - 1] =~ pttn) 

起動時チェック

weztermの機能で動作するので、GnomeTermialやWindowsTerminalから起動したときにはエラーを出して終了するようにする。

if !ENV['WEZTERM_PANE'] then
  puts "This program can only be launched from wezterm."
  exit 1
end

一通り機能するツールに仕立てる

wezsshという名前のツールに仕立てる。

usage: wezssh ユーザー名:パスワード@ホスト名[:ポート番号]

例:
$ wezssh myname:mypass@myhost

#coding: ascii

if !ENV['WEZTERM_PANE'] then
  puts "This program can only be launched from wezterm."
  exit 1
end

$USER = ""
$PASS = ""
$HOST = ""
$PORT = ""

if (ARGV.size == 1) \
 && (m = ARGV[0].match(/([^:]+):([^@]+)@([^:]+)(:.*)?$/)) then
  $USER = m[1]
  $PASS = m[2]
  $HOST = m[3]
  $PORT = (m[4] ? m[4].slice(1, m[4].size - 1) : "22")
else
  puts "usage:#{File.basename($PROGRAM_NAME, '.rb')} user:pass@host[:port]"
  exit 1
end

Thread.new() { 
  pttn = /#{$USER}@#{$HOST}'s password:$/
  secs = 1
  begin
    sleep secs
    secs = (secs < 64) ? (secs * 2) : 64
    lines = open("|wezterm cli get-text").read.chomp.split(/\n/).map { |s|
      s = s.strip
    }
    lines.delete('')
  end until (lines.size > 0) && (lines[lines.size - 1] =~ pttn) 
  open("|wezterm cli send-text", 'w') { |out|
    out.print "#{$PASS}\r"
  }
}

system "ssh -p #{$PORT} #{$USER}@#{$HOST}"

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?