免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 8502 | 回复: 10
打印 上一主题 下一主题

[学习共享] 求助,关于shell内使用tee记录日志,同时获取函数返回值。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-11-28 18:22 |只看该作者 |倒序浏览
5可用积分
我是想在入口函数直接加上 tee命令将标准输出打印在屏幕的同时,也记录到文件中。 同时也希望能够捕捉到main的返回值。

但是发现在使用了管道符号之后,main的返回值取不到了,$?代表的是管道之后命令的返回值。  本想用一个全局变量retCode来记录main的退出值,但发现retCode的修改同样无法传出main函数外部。

请教解决方案,谢谢!
  1. #!/bin/bash
  2. retCode=0
  3. function main()
  4. {
  5.    retCode=100
  6.    exit 100
  7. }

  8. main 2>&1 | tee -a logfile
  9. echo $?
  10. echo $reCode
复制代码

论坛徽章:
0
2 [报告]
发表于 2013-11-28 19:22 |只看该作者
自问自答吧。

网上查来的,bash解决方案如下:
The exit codes are provided in the PIPESTATUS special array. cmd1 exit code is in ${PIPESTATUS[0]}, cmd3 exit code in ${PIPESTATUS[2]}, so that $? is always the same as ${PIPESTATUS: -1}.

所以以上问题只需要判断 ${PIPESTATUS[0]},就是main的退出码了。。

同样也可以在执行main之前设置:set -o pipefail, 就可以用$?的值了。

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
3 [报告]
发表于 2013-11-28 19:25 |只看该作者
函数跟管道结合在一起,似乎是变成了一个subshell了,所以遇到了exit,脚本也没有退出,函数里的变量也获取不到(子进程嘛,退出了啥也没了),这种情况以前还真没注意,有点儿意思,我暂时也没找到相关的文档,等待高手回答。

论坛徽章:
5
白羊座
日期:2014-10-28 11:23:27水瓶座
日期:2015-01-20 10:19:022015亚冠之柏斯波利斯
日期:2015-07-11 18:17:2015-16赛季CBA联赛之同曦
日期:2015-12-23 12:38:582016猴年福章徽章
日期:2016-02-18 15:30:34
4 [报告]
发表于 2013-11-28 19:25 |只看该作者
回复 2# legone2008
学习了


   

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
5 [报告]
发表于 2013-11-28 19:31 |只看该作者
回复 2# legone2008


    学习了。还真是,求源链接说明文档

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
6 [报告]
发表于 2013-11-28 19:43 |只看该作者
打开ABS,看看第106页。这是@Shell_HAT大侠的惯用语,同时问下大侠,楼主这一例,main 后接管道,而main里有exit,却没有退出脚本,是否是这样的方式成了subshell?

Advanced Bash-Scripting Guide 3.9.1 中文版.pdf
http://bbs.chinaunix.net/thread-1610033-1-1.html

论坛徽章:
60
20周年集字徽章-20	
日期:2020-10-28 14:04:3015-16赛季CBA联赛之北京
日期:2016-07-06 15:42:0715-16赛季CBA联赛之同曦
日期:2016-06-12 10:38:0915-16赛季CBA联赛之佛山
日期:2016-05-27 11:54:56黄金圣斗士
日期:2015-12-02 11:44:35白银圣斗士
日期:2015-11-25 14:32:43白银圣斗士
日期:2015-11-23 12:53:352015亚冠之布里斯班狮吼
日期:2015-10-21 16:55:482015亚冠之首尔
日期:2015-09-01 16:46:052015亚冠之德黑兰石油
日期:2015-08-31 11:39:192015亚冠之萨济拖拉机
日期:2015-08-28 21:06:5315-16赛季CBA联赛之广东
日期:2016-07-12 14:58:53
7 [报告]
发表于 2013-11-28 20:08 |只看该作者
本帖最后由 reyleon 于 2013-11-28 20:19 编辑


http://www.unix.com/showthread.php?p=302265010
  1. ======================================================================

  2. 13. How do I get the exit code of cmd1 in cmd1|cmd2

  3.     First, note that cmd1 exit code could be non-zero and still don't
  4.     mean an error. This happens for instance in

  5.     cmd | head -1

  6.     you might observe a 141 (or 269 with ksh93) exit status of cmd1,
  7.     but it's because cmd was interrupted by a SIGPIPE signal when
  8.     "head -1" terminated after having read one line.

  9.     To know the exit status of the elements of a pipeline
  10.     cmd1 | cmd2 | cmd3

  11.     a. with zsh:

  12.        The exit codes are provided in the pipestatus special array.
  13.        cmd1 exit code is in $pipestatus[1], cmd3 exit code in
  14.        $pipestatus[3], so that $? is always the same as
  15.        $pipestatus[-1].

  16.     b. with bash:

  17.        The exit codes are provided in the PIPESTATUS special array.
  18.        cmd1 exit code is in ${PIPESTATUS[0]}, cmd3 exit code in
  19.        ${PIPESTATUS[2]}, so that $? is always the same as
  20.        ${PIPESTATUS: -1}.

  21.     c. with any other Bourne like shells

  22.        You need to use a trick to pass the exit codes to the main
  23.        shell.  You can do it using a pipe(2). Instead of running
  24.        "cmd1", you run "cmd1; echo $?" and make sure $? makes it way
  25.        to the shell.

  26.        exec 3>&1
  27.        eval `
  28.          # now, inside the `...`, fd4 goes to the pipe
  29.          # whose other end is read and passed to eval;
  30.          # fd1 is the normal standard output preserved
  31.          # the line before with exec 3>&1
  32.          exec 4>&1 >&3 3>&-
  33.          {
  34.            cmd1 4>&-; echo "ec1=$?;" >&4
  35.          } | {
  36.            cmd2 4>&-; echo "ec2=$?;" >&4
  37.          } | cmd3
  38.          echo "ec3=$?;" >&4
  39.        `

  40.     d. with a POSIX shell

  41.        You can use this function to make it easier:

  42.        run() {
  43.          j=1
  44.          while eval "\${pipestatus_$j+:} false"; do
  45.            unset pipestatus_$j
  46.            j=$(($j+1))
  47.          done
  48.          j=1 com= k=1 l=
  49.          for a; do
  50.            if [ "x$a" = 'x|' ]; then
  51.              com="$com { $l "'3>&-
  52.                          echo "pipestatus_'$j'=$?" >&3
  53.                        } 4>&- |'
  54.              j=$(($j+1)) l=
  55.            else
  56.              l="$l \"\$k\""
  57.            fi
  58.            k=$(($k+1))
  59.          done
  60.          com="$com $l"' 3>&- >&4 4>&-
  61.                     echo "pipestatus_'$j'=$?"'
  62.          exec 4>&1
  63.          eval "$(exec 3>&1; eval "$com")"
  64.          exec 4>&-
  65.          j=1
  66.          while eval "\${pipestatus_$j+:} false"; do
  67.            eval "[ \$pipestatus_$j -eq 0 ]" || return 1
  68.            j=$(($j+1))
  69.          done
  70.          return 0
  71.        }
  72.       
  73.        use it as:
  74.       
  75.        run cmd1 \| cmd2 \| cmd3
  76.        exit codes are in $pipestatus_1, $pipestatus_2, $pipestatus_3

  77. ======================================================================
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2013-11-28 20:30 |只看该作者
  1. 不明觉厉
复制代码

论坛徽章:
6
摩羯座
日期:2013-08-24 10:43:10狮子座
日期:2013-08-25 10:27:06天秤座
日期:2013-09-11 20:28:44午马
日期:2014-09-28 16:06:0015-16赛季CBA联赛之八一
日期:2016-12-19 13:55:0515-16赛季CBA联赛之天津
日期:2016-12-20 14:01:23
9 [报告]
发表于 2013-11-28 22:23 |只看该作者
用一个文件来记录函数的退出值

论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
10 [报告]
发表于 2013-11-29 08:27 |只看该作者
回复 1# legone2008

在 函数里 用 exit 还想拿到 返回值, 有性格.

体育老师告诉我, 函数 要用 return 才会 返回到主程序, exit 就退出程序直接返回系统了.


   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP