Alternative for bash's 'read -t' in POSIX shell

huangapple go评论61阅读模式
英文:

Alternative for bash's 'read -t' in POSIX shell

问题

I'm currently working on a college project where I have to do several shell script files. In one of them, I have to create a file called taunt.sh that uses the command cowsay to print some messages depending on some actions:

  1. If no message is received after 10 seconds then the taunt.sh script should issue a funny message and finish/exit.
  2. If it receives the SIGHUP signal, then it should issue a special message and exit.
  3. If it receives a SIGINT or SIGTERM, then it should issue a taunt and terminate/exit.

The thing is, I need to use #!/bin/sh and not #!/bin/bash.

I know in bash we can use read -t 10 input to wait for 10 seconds while an input is received, and we could exit of the waiting process after receiving some input.

But this is not an option in sh.

So, is there a way to implement some similar functionality in sh?

I tried this

#!/bin/sh

echo "Enter your input:"
sleep 10 &
read input
kill $! 2>/dev/null

if [ -z "$input" ]; then
  echo "No input provided"
else
  echo "You entered: $input"
fi

But it never got out after 10 seconds, only if I typed something.

I'm pretty new to sh and still takes me a while to understand some things. So I hope somebody can help me with this.

英文:

I'm currently working on a college project where I have to do several shell script files. In one of them, I have to create a file called taunt.sh that uses the command cowsay to print some messages depending on some actions:

  1. If no message is received after 10 seconds then the taunt.sh script should issue a funny message and finish/exit.
  2. If it receives the SIGHUP signal, then it should issue a special message and exit.
  3. If it receives a SIGINT or SIGTERM, then it should issue a taunt and terminate/exit.

The thing is, I need to use #!/bin/sh and not #!/bin/bash.

I know in bash we can use read -t 10 input to wait for 10 seconds while an input is received, and we could exit of the waiting process after receiving some input.

But this is not an option in sh.

So, is there a way to implement some similar functionality in sh?

I tried this

#!/bin/sh

echo "Enter your input:"
sleep 10 &
read input
kill $! 2>/dev/null

if [ -z "$input" ]; then
  echo "No input provided"
else
  echo "You entered: $input"
fi

But it never got out after 10 seconds, only if I typed something.

I'm pretty new to sh and still takes me a while to understand some things. So I hope somebody can help me with this.

答案1

得分: 3

以下是已翻译的内容:

这是一个 POSIX 版本的bash的 read -t 10

#!/usr/bin/env sh

timeout=10
mystty="$(stty -g)"
trap 'stty "$mystty"' EXIT   
stty -icanon min 0 time $((timeout*10))

echo "请输入您的输入"
read input

if [ -z "$input" ]; then
  echo "未提供输入"
else
  echo "您输入的是: $input"
fi
  • mystty="$(stty -g)":将 stty 设置保存在变量中。
  • trap 'stty "$mystty"' EXIT:这一行为 EXIT 信号设置了一个陷阱。在这种情况下,当脚本退出时,无论是通过 ctrl+c 还是其他退出方式,它都会恢复终端的设置。
  • stty -icanon min 0 time 100:这一行使用 stty 命令修改终端设置。-icanon 标志禁用规范模式,这意味着输入会立即处理,而不会等待换行符。min 0 设置表示终端不会等待任何字符输入即可返回。time 100 设置了一个100个十分之一秒(10秒)的超时来读取输入。在此模式下,如果在指定的超时内未收到输入,读取操作将立即返回。

【注】:POSIX trap exit

英文:

Here a POSIX version of the bash's read -t 10:

#!/usr/bin/env sh

timeout=10
mystty="$(stty -g)"
trap 'stty "$mystty"' EXIT   
stty -icanon min 0 time $((timeout*10))

echo "Enter your input "
read input

if [ -z "$input" ]; then
  echo "No input provided"
else
  echo "You entered: $input"
fi

  • mystty="$(stty -g)" save stty settings in a variable
  • trap &#39;stty &quot;$mystty&quot;&#39; EXIT: This line set a trap for the EXIT¹ signal. In this case, when the script exits, it will restores those settings in any cases (<kbd>ctrl+c</kbd> or any exit cases) for the following terminal modifications :
  • stty -icanon min 0 time 100: This line modifies the terminal settings using the stty command. The -icanon flag disables canonical mode, which means that input is processed immediately, without waiting for a newline character. The min 0 setting means that the terminal will not wait for any characters to be typed before returning input. The time 100 set a timeout of 100 deciseconds (10 seconds) to read input. In this mode, if no input is received within the specified timeout, the read operation will return immediately.

¹ POSIX trap exit

huangapple
  • 本文由 发表于 2023年5月15日 08:41:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76250248.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定