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

时间:2022-07-07 22:22:44

I am trying to use script command for logging a bash session.

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

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

脚本命令从运行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

谢谢

5 个解决方案

#1


17  

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

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

The use case for script is:

脚本的用例是:

  1. start script (spawns a new shell)
  2. 启动脚本(生成一个新的shell)
  3. do commands
  4. 做命令
  5. exit shell (logout) and drop to previous shell
  6. 退出shell(注销)并将其删除到以前的shell
  7. examine or print logfile created by script
  8. 检查或打印脚本创建的日志文件

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

基本上脚本就像预期的那样工作。你必须找到另一种方法来实现你想要的。

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>&1 redirects stdout and stderr to logfile
  • 执行> logfile 2>&1将stdout和stderr重定向到logfile
  • set -x makes bash print every command before executing it
  • 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

#2


5  

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

您的bash脚本仍然在运行,但是它已经生成了一个新的交互式shell。bash脚本正在等待脚本完成,这只会在交互式shell终止时发生(通过被终止,或者通过用户输入exit)。

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

要让脚本记录命令after script,请这样做:

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

However, script will stop running after running that command.

但是,在运行该命令后,脚本将停止运行。

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 -c option.

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

#3


3  

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

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

#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1 $0 $@"
# your script here...

#4


2  

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 [ "$1" != "noscript" ] ; then
        # execute self with the noscript special arg so that the second execution DOES NOT start script again.
        exec script -q -c "$0 noscript $1 $2 $3" /build/buildlog_`date '+%Y%m%d%H%M%S'`.log
        echo Problem in $0, 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 :).

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

#5


1  

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的回答很好,但没有正确地传递论点。基本的问题是在双引号字符串中使用$@。使用$*代替:

#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1  $0 $*"
# your script here...

Here's what happens with $@:

下面是$@的情况:

foo.sh:

foo.sh:

#!/bin/sh
if [ -z $FOO ]
then
    FOO=1 exec $0 $@
else
    ./echo_args.sh "$0 $@"
fi

bar.sh:

bar.sh:

#!/bin/sh
echo 0 $0
echo 1 $1
echo 2 $2
echo 3 $3

Now ./foo.sh with some arguments outputs

现在。/ foo。带一些参数的sh输出

0 ./bar.sh
1 /path/to/foo.sh with
2 some
3 arguments

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

这将导致一些参数被传递给脚本,而不是传给foo.sh的第二次执行。

#1


17  

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

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

The use case for script is:

脚本的用例是:

  1. start script (spawns a new shell)
  2. 启动脚本(生成一个新的shell)
  3. do commands
  4. 做命令
  5. exit shell (logout) and drop to previous shell
  6. 退出shell(注销)并将其删除到以前的shell
  7. examine or print logfile created by script
  8. 检查或打印脚本创建的日志文件

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

基本上脚本就像预期的那样工作。你必须找到另一种方法来实现你想要的。

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>&1 redirects stdout and stderr to logfile
  • 执行> logfile 2>&1将stdout和stderr重定向到logfile
  • set -x makes bash print every command before executing it
  • 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

#2


5  

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

您的bash脚本仍然在运行,但是它已经生成了一个新的交互式shell。bash脚本正在等待脚本完成,这只会在交互式shell终止时发生(通过被终止,或者通过用户输入exit)。

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

要让脚本记录命令after script,请这样做:

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

However, script will stop running after running that command.

但是,在运行该命令后,脚本将停止运行。

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 -c option.

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

#3


3  

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

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

#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1 $0 $@"
# your script here...

#4


2  

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 [ "$1" != "noscript" ] ; then
        # execute self with the noscript special arg so that the second execution DOES NOT start script again.
        exec script -q -c "$0 noscript $1 $2 $3" /build/buildlog_`date '+%Y%m%d%H%M%S'`.log
        echo Problem in $0, 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 :).

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

#5


1  

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的回答很好,但没有正确地传递论点。基本的问题是在双引号字符串中使用$@。使用$*代替:

#!/bin/sh
[ -z "$TYPESCRIPT" ] && TYPESCRIPT=1 exec /usr/bin/script -c "TYPESCRIPT=1  $0 $*"
# your script here...

Here's what happens with $@:

下面是$@的情况:

foo.sh:

foo.sh:

#!/bin/sh
if [ -z $FOO ]
then
    FOO=1 exec $0 $@
else
    ./echo_args.sh "$0 $@"
fi

bar.sh:

bar.sh:

#!/bin/sh
echo 0 $0
echo 1 $1
echo 2 $2
echo 3 $3

Now ./foo.sh with some arguments outputs

现在。/ foo。带一些参数的sh输出

0 ./bar.sh
1 /path/to/foo.sh with
2 some
3 arguments

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

这将导致一些参数被传递给脚本,而不是传给foo.sh的第二次执行。