Bash 脚本:使用 bash 脚本中的“脚本”命令记录会话

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5985060/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 00:55:13  来源:igfitidea点击:

Bash script: Using "script" command from a bash script for logging a session

linuxbash

提问by limp

I am trying to use scriptcommand for logging a bash session.

我正在尝试使用script命令来记录 bash 会话。

The scriptcommand is executed from withing a bash script but as soon as it is executed, the bash script terminates.

script命令是通过 bash 脚本执行的,但是一旦执行,bash 脚本就会终止。

I have tried to invoke the command using various combination always with the same result (termination of the bash script as soon as the command is called). The output that I get is the following:

我尝试使用各种组合调用命令,结果始终相同(调用命令后立即终止 bash 脚本)。我得到的输出如下:

Script started, file is typescript
root@ubuntu: ...

I have also tried to invoke the command with an &in the end but again with no luck.

我也尝试在最后调用命令,&但再次没有运气。

Can anyone tell me how should I invoke the command from a bash script?

谁能告诉我应该如何从 bash 脚本调用命令?

Thanks

谢谢

采纳答案by lesmana

Your shell script did not terminate. It is still running. You are getting a prompt because scriptis spawning a new shell.

您的 shell 脚本没有终止。它仍在运行。您收到提示,因为script正在生成一个新的 shell。

The use case for scriptis:

的用例script是:

  1. start script(spawns a new shell)
  2. do commands
  3. exit shell (logout) and drop to previous shell
  4. examine or print logfile created by script
  1. 开始script(产生一个新的外壳)
  2. 做命令
  3. 退出外壳(注销)并下降到前一个外壳
  4. 检查或打印由 script

So basically scriptis working as expected. You will have to find another way to achieve what you want.

所以基本上script按预期工作。你必须找到另一种方式来实现你想要的。

You can log the execution of your script like this:

您可以像这样记录脚本的执行:

#! /bin/bash
exec > logfile 2>&1
set -x
FOO=BAR
echo $FOO

Explanation:

解释:

  • exec > logfile 2>&1redirects stdout and stderr to logfile
  • set -xmakes bash print every command before executing it
  • exec > logfile 2>&1将 stdout 和 stderr 重定向到日志文件
  • set -x使 bash 在执行之前打印每个命令

Example:

例子:

$ ./foo.sh
$ cat logfile 
+ FOO=BAR
+ echo BAR
BAR

Disadvantage of this method is that the script prints no output for humans to see. Everything goes to the logfile.

这种方法的缺点是脚本不打印输出供人类查看。一切都进入日志文件。

Alternatively you can do it like this:

或者,您可以这样做:

#! /bin/bash
# nothing special here
FOO=BAR
echo $FOO

Then execute like this:

然后像这样执行:

$ script -c "bash -x foo.sh"
Script started, file is typescript
+ FOO=BAR
+ echo BAR
BAR
Script done, file is typescript
$ cat typescript 
Script started on Mi 18 Mai 2011 01:05:29 CEST
+ FOO=BAR
+ echo BAR
BAR

Script done on Mi 18 Mai 2011 01:05:29 CEST

回答by Robin Green

Your bash script is still running, but it has spawned a new interactive shell. The bash script is waiting for scriptto complete, which will only happen when the interactive shell is terminated (either by being killed, or by the user typing exit).

您的 bash 脚本仍在运行,但它产生了一个新的交互式 shell。bash 脚本正在等待script完成,这只会在交互式 shell 终止时发生(要么被杀死,要么用户输入exit)。

To make the command after scriptbe logged by script, do it like this:

要在script被登录后执行命令script,请执行以下操作:

script build_log -c 'echo -e "* This line should appear inside the /"build_log/" log file..."'

However, scriptwill stop running after running that command.

但是,script运行该命令后将停止运行。

To run multiple commands inside script, put those commands inside another bash script and specify that bash script as the command to run to the -coption.

要在 中运行多个命令script,请将这些命令放在另一个 bash 脚本中,并将该 bash 脚本指定为要运行到该-c选项的命令。

回答by execve

You can use a trick within your shell script to start script or not start it. Based on a special argument, it can choose to execute itself with a special argument so that script is not started again.

您可以在 shell 脚本中使用一个技巧来启动或不启动它。基于一个特殊的参数,它可以选择用一个特殊的参数执行自己,这样脚本就不会再次启动。

This should most likely explain what I mean:

这应该最有可能解释我的意思:

if [ "" != "noscript" ] ; then
        # execute self with the noscript special arg so that the second execution DOES NOT start script again.
        exec script -q -c "
#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1 
#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1  
#!/bin/sh
if [ -z $FOO ]
then
    FOO=1 exec 
#!/bin/sh
echo 0 
0 ./bar.sh
1 /path/to/foo.sh with
2 some
3 arguments
echo 1 echo 2 echo 3
$@ else ./echo_args.sh "##代码## $@" fi
$*" # your script here...
$@" # your script here...
noscript " /build/buildlog_`date '+%Y%m%d%H%M%S'`.log echo Problem in ##代码##, please check. exit 1; fi ...Rest of the script should follow here.

I have tried this, and it works well. Unless you are particular about the kind of arguments that need to be passed as well as the script is planned to be used by hostile users, this should suffice :).

我试过这个,效果很好。除非您特别关注需要传递的参数类型以及计划由敌对用户使用的脚本,否则这应该就足够了:)。

回答by juj

Following execve's idea, you can also use an environment variable:

按照 execve 的想法,您还可以使用环境变量:

##代码##

回答by Tim Cooijmans

juj's answer is great but fails to pass on arguments correctly. The basic problem is the use of $@inside a double-quoted string. $*should be used instead:

juj 的回答很好,但未能正确传递论点。基本问题是在$@双引号字符串里面的使用。$*应该改用:

##代码##

Here's what happens with $@:

这是发生了什么$@

foo.sh:

foo.sh

##代码##

bar.sh:

bar.sh

##代码##

Now ./foo.sh with some argumentsoutputs

现在./foo.sh with some arguments输出

##代码##

This would cause some of the arguments to be passed to scriptinstead of to the second execution of foo.sh.

这将导致将某些参数传递给script而不是传递给foo.sh.