Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/28.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux bash中具有多个shell的作业控制?_Linux_Bash - Fatal编程技术网

Linux bash中具有多个shell的作业控制?

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脚本非常陌生

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

下面是一个快速概述:

  • 执行一些bash cmds(提示输入用户名/密码)
  • 计算一些东西
  • 在bash中启动expect shell
    • expect使用特定用户名启动wadm
      • wadm提示输入密码
      • expect输入密码
      • expect运行特定于wadm的cmds
      • 退出wadm(期望向wadm发送“退出”)
    • 退出expect(expect在bash脚本中结束)
  • 编辑上述wadm cmds创建的一些文件
  • 在bash中启动expect shell
    • expect使用特定用户名启动wadm
      • wadm提示输入密码
      • expect输入密码
      • expect运行特定于wadm的CMD(依赖于以前wadm CMD的不同CMD)
      • 退出wadm(期望向wadm发送“退出”)
    • 退出expect(expect在bash脚本中结束)
我想做的是让expect和wadm在后台运行(不要每次需要在wadm中执行某些操作时都启动/退出wadm),同时在bash中执行其他操作

作为bash脚本的新手(同样,我在linux/unix方面也不是很先进),我曾想过使用作业控制来实现这一点,但根据这篇文章(http://stackoverflow.com/questions/690266/why-cant-i-use-job-control-in-a-bash-script)
作业控制可能不是解决问题的办法。此类流程还有哪些其他选项?

创建两个命名管道:

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;