Linux bash中具有多个shell的作业控制?
首先,我对bash脚本非常陌生 我有一个bash脚本来开始创建环回服务器。它执行一些bash命令,然后运行'expect',然后启动一个名为wadm的程序(expect处理wadm提示的密码) 下面是一个快速概述:Linux bash中具有多个shell的作业控制?,linux,bash,Linux,Bash,首先,我对bash脚本非常陌生 我有一个bash脚本来开始创建环回服务器。它执行一些bash命令,然后运行'expect',然后启动一个名为wadm的程序(expect处理wadm提示的密码) 下面是一个快速概述: 执行一些bash cmds(提示输入用户名/密码) 计算一些东西 在bash中启动expect shell expect使用特定用户名启动wadm wadm提示输入密码 expect输入密码 expect运行特定于wadm的cmds 退出wadm(期望向wadm发送“退出”)
- 执行一些bash cmds(提示输入用户名/密码)
- 计算一些东西
- 在bash中启动expect shell
- expect使用特定用户名启动wadm
- wadm提示输入密码
- expect输入密码
- expect运行特定于wadm的cmds
- 退出wadm(期望向wadm发送“退出”)
- 退出expect(expect在bash脚本中结束)
- expect使用特定用户名启动wadm
- 编辑上述wadm cmds创建的一些文件
- 在bash中启动expect shell
- expect使用特定用户名启动wadm
- wadm提示输入密码
- expect输入密码
- expect运行特定于wadm的CMD(依赖于以前wadm CMD的不同CMD)
- 退出wadm(期望向wadm发送“退出”)
- 退出expect(expect在bash脚本中结束)
- expect使用特定用户名启动wadm
作业控制可能不是解决问题的办法。此类流程还有哪些其他选项?创建两个命名管道:
mkfifo wadm_stdin
mkfifo wadm_stdout
在后台启动wadm:
wadm <wadm_stdin >wadm_stdout &
wadm_id=$!
完成wadm后,等待其退出:
cat wadm_stdout >/dev/null & # Read any output to prevent blocking on a full pipe
echo quit >wadm_stdin
wait $wadm_id
通常,您不会与脚本交互,然后将其发送到后台—您可以选择一个。但是在linux上的cource,一切都是可能的 这里的主要问题是管道(stdout/stderr):您不能只是在那个时关闭,脚本很可能在写入管道结束出口本身时出错。因此,您需要重定向现有管道。我不知道有什么标准工具可以做到这一点,但它可以通过gdb实现 工作控制也是一个有争议的话题。如果您没有编写商业脚本,那么在每台服务器上实施作业控制可能会更容易,然后进行一些变通。但在这种情况下,您必须知道的唯一一件事是父shell将在退出时向所有子进程发送SIGHUP,因此在这种情况下,最好关闭它,或者使用陷阱忽略它(就像我所做的那样) 现在,我将描述一种实现您所需的方法 首先,确保gdb可以连接到同一用户运行的进程。默认情况下,它在许多系统上启用,但有些系统只允许root用户执行此操作。通常,您可以通过将/proc/sys/kernel/yama/ptrace_scope设置为0(这样做可能不安全)来改变这一点。运行“gdb-psome_-pid”检查它是否工作,“some_-pid”-用户运行的任何进程的pid 由于gdb在读取stding时似乎有一些问题,请在系统中的某个位置设置一个文件(在我的示例中为/usr/share/gdb_null_descr),其中包含以下内容:
p dup2(open("/dev/null",0),1)
p dup2(open("/dev/null",0),2)
这将告诉gdb在它附加到的进程中将STDOUT和STDERR重定向到/dev/null(如果您想保存它,您可以将它更改为任何其他文件,但请谨慎使用权限)
现在,一切都很简单。为了进行测试,在本例中创建一些简单的守护进程,如daemon.sh:
#!/bin/bash
success=0;
while [ "$success" -lt 1 ]
do
echo "Give me username!";
read username;
echo "Give me password!";
read password;
if [[ "$username" = "root" && "$password" = "rootpass" ]]
then
success=1;
else
echo "Invalid username/password!";
fi;
done;
echo "Logged in succesfully!";
echo -n > test_file;
loop_count=0;
while [ 1 ]
do
echo "Still working";
if [ "$loop_count" -eq 100 ]
then
loop_count=0;
echo "Please, kill me, I am tired!";
fi;
let loop_count++;
echo "$loop_count" >> test_file;
sleep 1;
done;
现在,我们的expect脚本:
#!/usr/bin/expect
#Just never timeout
set timeout -1;
#Start bash process - we need it only to set trap
spawn bash;
#Set trap on SIGHUP to nothing - bash will just ignore this signal.
send "trap '' HUP;\n";
#Start our half-daemon by replacing this bash process (using exec).
send "exec ./daemon.sh;\n";
#ineract with half-daemon
expect *username!;
send "root\n";
expect *password!;
send "rootpass\n";
#Ok, interaction ends, redirect pipes
system gdb -p [exp_pid] --batch -x /usr/share/gdb_null_descr;
现在,运行expect脚本并查看test_文件-如果每秒都有新条目出现,则妖魔化成功完成 对不起,格式不好。我不太确定我是否遵循了这一行:wadm wadm\u stdout&我运行expect/wadm的代码片段如下:
expect-c“stty-echo set password$PASSW spaw$WORKDIR/bin/wadm--user=$yourUID expect\”请输入管理员用户密码>\“send\”$password\r\“expect{-re\”无效用户或密码\“{exit 3}”wadm>\“{send\”copy config--config=$oldud-$MAXPORT$1-$NP\r\”}预期\“wadm>\”send\“quit\r\”
是wadm wadm-u标准输出&
表示wadm-u标准输入将通过管道传输到wadm,而wadm
标准输出将通过管道传输到wadm-u标准输出。
是的,这正是它的意思。
#!/usr/bin/expect
#Just never timeout
set timeout -1;
#Start bash process - we need it only to set trap
spawn bash;
#Set trap on SIGHUP to nothing - bash will just ignore this signal.
send "trap '' HUP;\n";
#Start our half-daemon by replacing this bash process (using exec).
send "exec ./daemon.sh;\n";
#ineract with half-daemon
expect *username!;
send "root\n";
expect *password!;
send "rootpass\n";
#Ok, interaction ends, redirect pipes
system gdb -p [exp_pid] --batch -x /usr/share/gdb_null_descr;