2

在过去的两天里,我遇到了一个问题。

我正在运行一个 tcl 脚本(对于一个 eggdrop),当它被触发时,它会执行一个本地 shell 命令(子进程),如果命令成功,它会吐出结果。但是,如果命令不成功,我会收到一个错误“ Tcl error [proc_ports]: child process exited abnormally:.

如果子进程没有找到任何结果,我想要创建一个自定义响应。

脚本是:

set chan "#help"
bind pub -|- .port proc_ports

proc proc_ports {nick host handle channel testes} {
    global chan
    if {"$chan" == "$channel"} {
        return 0
    }

    if [matchattr $nick |fmn $channel] {
        set ports [lindex $testes 0]
        set fp [ exec grep -w "$ports" scripts/ports | awk {{$1=""; print $0}} ]

        putserv "PRIVMSG $channel :Port \002$ports\002 is normally used for: \002$fp\002"

        return 1
    } else {
        putserv "PRIVMSG $channel :$nick, you do \002NOT\002 have access to this command!"
        return 1
    }
}

我很想使用 TCL 解决这个问题,以帮助我了解更多信息,而不是将 exec 更改为会返回任何错误的 shell 脚本。

我已经阅读了 TCL 中的 CATCH 命令,并尝试了许多不同的脚本方法,但是都失败了:(

任何帮助,将不胜感激。

干杯。

4

2 回答 2

4
  1. 你有巨大的安全问题。1a) 变量“testes”包含用户文本。您认为“testes”包含有效的 TCL 列表并在其上使用“lindex”。您应该至少使用命令set ports [lindex [split $testes] 0] 1b) 在发送自定义文本以在 shell 中运行之前,您应该检查它是否包含非法字符。使用string is, regexp, regsub.

  2. 要检查命令执行中的错误,您可以使用以下代码:

    set ports [lindex $testes 0]
    if { [catch {exec grep -w "$ports" scripts/ports | awk {{$1=""; print $0}}} fp] } {   
      putserv "PRIVMSG $channel :Something wrong while executing command."
    } {
      putserv "PRIVMSG $channel :Port \002$ports\002 is normally used for: \002$fp\002"
    }
    
于 2013-02-10T13:04:35.027 回答
3

这里有几个问题。首先,exec当它运行的管道以非零退出代码退出而不写入stderr. 其次,grep当它没有找到任何东西时,它的退出代码为 1。这两个功能不能很好地结合在一起!

最简单的解决方法是这样做:

if {[catch {
    set fp [ exec grep -w "$ports" scripts/ports | awk {{$1=""; print $0}} ]
    putserv "PRIVMSG $channel :Port \002$ports\002 is normally used for: \002$fp\002"
}]} {
    putserv "PRIVMSG $channel :Port \002$ports\002 not in port database"
}

这是有效的,因为catch如果发生错误,结果为 1,如果没有错误,结果为 0。我们假设所有错误都是由于没有找到任何东西(这不是一个好主意,但很方便!),但如果这让您感到困扰,Tcl 8.6 的try命令更具辨别力。

于 2013-02-10T13:06:17.810 回答