在bash中使用多个shell进行作业控制?

时间:2011-08-26 13:20:18

标签: linux bash

首先,我是新手来编写脚本。

好吧,我有一个bash脚本来开始创建一个环回服务器。哪一个bash命令,然后运行'expect'然后启动一个名为wadm的程序(期望处理密码wadm提示)。

这是一个快速概述:

  • 做一些bash cmds(提示输入用户名/通行证)
  • 计算一些东西
  • 在bash中开始期待shell
    • 期望用特定的用户名启动wadm
      • wadm提示输入密码
      • 期望输入密码
      • 期望运行特定于wadm的cmds
      • 退出wadm(期待发送'退出'到wadm')
    • 退出期望(期望在bash脚本中结束)
  • 编辑上述wadm cmds创建的一些文件
  • 在bash中开始期待shell
    • 期望用特定的用户名启动wadm
      • wadm提示输入密码
      • 期望输入密码
      • 期望运行特定于wadm的cmds(依赖于之前的wadm cmds的不同cmds)
      • 退出wadm(期待发送'退出'到wadm')
    • 退出期望(期望在bash脚本中结束)

我想做的是保持期望和wadm在后台运行(每次我需要在其中执行某些操作时不启动/退出wadm),而我在bash中执行其他操作。

成为bash脚本的新手(同样,我在linux / unix中不是那么先进)我想过使用作业控制来解决这个问题,但根据这篇文章(http://stackoverflow.com/questions/690266/)为什么-着,我使用的作业控制-IN-A-的bash脚本) 工作控制可能不是可行的方法。这种过程有哪些其他选择?

2 个答案:

答案 0 :(得分:1)

创建两个命名管道:

mkfifo wadm_stdin
mkfifo wadm_stdout

在后台启动wadm:

wadm <wadm_stdin >wadm_stdout &
wadm_id=$!

根据需要多次使用expect的脚本(不要忘记第一次登录并从最后删除退出)

expect ... <wadm_stdout >wadm_stdin

完成wadm后,等待退出:

cat wadm_stdout >/dev/null &  # Read any output to prevent blocking on a full pipe
echo quit >wadm_stdin
wait $wadm_id

答案 1 :(得分:0)

通常您不与脚本交互,然后将其发送到后台 - 您选择一个。但是Linux上的cource一切皆有可能。

这里的主要问题是管道(stdout / stderr):你不能只关闭,脚本很可能在写入管道端口退出时会出错。因此,您需要重定向现有管道。我不知道任何可以做到这一点的标准工具,但可以使用gdb完成。

工作控制也是一个有争议的话题,imho。如果您没有编写商业脚本,那么在每个服务器上执行作业控制可能更容易,然后进行一些解决方法。但在这种情况下,你必须知道的唯一一件事就是父shell会在退出时将SIGHUP发送给所有子进程,所以最好在这种情况下关闭它,或者使用陷阱来忽略它(就像我做的那样) )。

现在,我将描述一种做你想做的事情的方法。

首先,确保gdb可以附加到从同一用户运行的运行进程。默认情况下,它在许多系统上启用,但有些只允许root用户执行此操作。通常可以通过将/ proc / sys / kernel / yama / ptrace_scope设置为0来更改它(这样做可能不安全)。运行“gdb -p some_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;

现在,我们的期望脚本:

#!/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_file - 如果每秒都有新条目出现,那就成功地进行了妖魔化!