gpt4 book ai didi

linux - 如何在 Bash 脚本中使用 Expect 生成预填充的终端 session

转载 作者:太空宇宙 更新时间:2023-11-04 12:25:38 25 4
gpt4 key购买 nike

几个月前我问了一个略有不同的版本,但一直没能正常工作,这个问题已经有了一些进展,有了新的代码块。

当我登录到我的各种 PC 时,我通常有很多事情想要自动发生,但并不总是立即发生。

这些包括在特定工作区的特定位置启动终端 session (因为您习惯于使用相同的布局)和那些执行特定操作的终端 session ,例如 ssh 命令(我不想以任何方式将密码嵌入到脚本中或管道,只是想将命令填充到终端 session 中,这样当我最终到达那个特定的终端 session 时,我只需要按回车键)。

然而,有时当您在重新启动后登录时,您可能不想立即执行这些命令,因为优先级更高的操作可能需要您首先注意。

所以....我想要的是我的登录脚本来打开终端 session 并在命令行上预先填充该特定终端 session 的 session 命令,但尚未执行。

我使用 Mate 和 Compiz 作为我的 DE,因为我喜欢它们的灵 active 。

目前我的 bash 脚本看起来像这样。

#!/bin/bash

# This script is to open a number of windows at specific locations and execute startup commands in those windows.
# It's designed to save time on a new boot up environment and keep the environment consistent.


# Define function to see which ViewPort we are currently on



CurrentViewportQuery () {

TOTALAREA=`wmctrl -d | awk '{print $4}' | awk -F'x' '{print $1}'`

VPAREA=`wmctrl -d | awk '{print $9}' | awk -F'x' '{print $1}'`

CURRENTVPORTREF=`wmctrl -d | awk '{print $6}' | awk -F',' '{print $1}'`

TOTALVPORTS=`echo "$TOTALAREA/$VPAREA" | bc`

CURRENTVPORT=`echo "($CURRENTVPORTREF/$VPAREA)+1" | bc`

}

# TerminalSessionTargets () {



CurrentViewportQuery

# echo "totalarea $TOTALAREA vparea $VPAREA currentvportref $CURRENTVPORTREF totalvports $TOTALVPORTS currentvport $CURRENTVPORT"

# exit 99 # Debug Exit Point

# The following sleep is to allow compiz to fire up fully before we open the terminal sessions or else compositing isn't enabled when the terminal sessions open leading to time based inconsistencies.

sleep 3

# The following defines the number of terminal session I want for this version of the script, the location onscreen and the target IP address for the ssh session
# In this instance 9 terminal sessions spread over 3 workspaces starting at workspace 3 (this version of the script runs on a machine with a 4k screen)

TERM[0]="24"
TERMLOC[0]="180+400"
TERM[1]="25"
TERMLOC[1]="1305+400"
TERM[2]="xxx"
TERMLOC[2]="2430+400"
TERM[3]="112"
TERMLOC[3]="180+400"
TERM[4]="117"
TERMLOC[4]="1305+400"
TERM[5]="xxx"
TERMLOC[5]="2430+400"
TERM[6]="191"
TERMLOC[6]="180+400"
TERM[7]="193"
TERMLOC[7]="1305+400"
TERM[8]="xxx"
TERMLOC[8]="2430+400"


STARTTERM="0"

FIRSTTARGETVPORT="3"
# FIRSTTARGETVPORT="5" # Temp line for code testing
LASTTARGETVPORT=$((TOTALVPORTS))
NUMBEROFTARGETVPORTS=$((TOTALVPORTS-(FIRSTTARGETVPORT-1)))
NUMBERTERMSPERVPORT=$((${#TERM[*]}/NUMBEROFTARGETVPORTS))

echo "last targetvport $LASTTARGETVPORT numbertargetvports $NUMBEROFTARGETVPORTS termspervport $NUMBERTERMSPERVPORT" # Debug output so I can confirm location of spawned terminal session


# Turn off touch sensitive screen

SCREENVALUE=`xinput | grep 'Touchscreen' | cut -f 2 | sed 's/id=//'`

xinput --set-prop $SCREENVALUE 'Device Enabled' 0

# exit

# First lets calculate how many workspaces we have on this machine

CurrentViewportQuery

# Now the dimensions of each viewport

for ((i=1;$i<=$(($TOTALAREA / $VPAREA));i++)); do
VPORT[$i]=$(($VPAREA * ($i-1))) #sets the array entry at index $i to the next viewsize. Remember that $i increases by one every loop

done

# Now lets open the sshdesktops desktops in viewport 3

FIRSTVPORTTERM="$STARTTERM"

let LASTVPORTTERM="$STARTTERM+($NUMBERTERMSPERVPORT-1)" # The -1 is to make sure the first term which is number 0 is included

for NEXTTARGETVPORT in `eval echo {$FIRSTTARGETVPORT..$LASTTARGETVPORT}`; do

echo "targetvport ${NEXTTARGETVPORT}"

wmctrl -o ${VPORT[NEXTTARGETVPORT]},0

until [ $CURRENTVPORT -eq $NEXTTARGETVPORT ]; do

CurrentViewportQuery

done

for THISVPORTSTERMS in `eval echo {$FIRSTVPORTTERM..$LASTVPORTTERM}`; do


expect -c " spawn -noecho mate-terminal --window-with-profile=default --geometry=85x24+${TERMLOC[THISVPORTSTERMS]} --title='SSH${TERM[THISVPORTSTERMS]}';
expect \">:\";
send \"ssh root@192.168.12.${TERM[THISVPORTSTERMS]}\";
interact;
expect eof;"

done

现在脚本在正确识别工作区、切换到正确的工作区和代码块底部附近的 expect -c 命令方面运行良好,但是在每个工作区的正确位置生成了 mate-terminal session 它没有使用所需的 ssh 命令填充终端 session (基本上 send\"ssh@192.168 ......"位不起作用)。

我已经尝试了各种语法版本,并且在我有几分钟时间的时候重新访问了几次......但到目前为止没有任何乐趣所以我回到这里再次询问。

最佳答案

如果您将示例减少到必要的最低限度,将会有所帮助。在你的情况下,问题是当你生成 mate-terminal 时,expect 在它和命令之间创建了一个伪 tty pty,但是随后 mate-terminal 创建另一个 pty 并在其中运行 shell。因此,您的 send 命令被发送到将要忽略它的对象。

例如,您需要做的是在 mate-terminal 中运行 expect 命令,如下所示:

mate-terminal -x expect -c 'spawn bash -i; send "echo hello";interact'

这仍然有点低效,因为我们仍然有两个 pty。因此,另一种方法是使用 ioctl TIOCSTI,它可以将字符推送到 pty 的输入端。编写一个简单的 perl 脚本,pushtype with

#!/usr/bin/perl
# push characters onto tty input queue as if typed
# see man tty_ioctl. https://stackoverflow.com/a/45130404/5008284
use strict;
require 'sys/ioctl.ph';
foreach my $ch (split('',join(" ",@ARGV))){
ioctl(STDOUT, &TIOCSTI, $ch) or die $!;
}

然后你就可以使用了

mate-terminal -x bash -c 'pushtype "echo hello"; exec bash -i'

并且您将在 shell 的输入中准备好 echo hello,而无需另一个 pty。

关于linux - 如何在 Bash 脚本中使用 Expect 生成预填充的终端 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44797703/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com