Shellscript抛出错误,但不知何故仍在工作

Shellscript抛出错误,但不知何故仍在工作,shell,Shell,我有这个shellscrip可以在另一台机器上部署travis的代码 #!/bin/sh codecov function sshDeploy { printf -v __ %q "$1" ssh -oStrictHostKeyChecking=no deployuser@178.62.252.23 "cd api; git pull origin master; git checkout $__;./sbt clean; ./sbt stage; ./neeedo restar

我有这个shellscrip可以在另一台机器上部署travis的代码

#!/bin/sh
codecov
function sshDeploy {
    printf -v __ %q "$1"
    ssh -oStrictHostKeyChecking=no deployuser@178.62.252.23 "cd api; git pull origin master; git checkout $__;./sbt clean; ./sbt stage; ./neeedo restart; exit $?"
}
sshDeploy $TRAVIS_COMMIT
exit $?
此脚本在我的macbook上运行时没有任何错误。然而,当我在travis上运行它时(不幸的是,我无法告诉您他们在构建代理上运行哪个unix,因为我无法直接访问它们),我观察到了奇怪的行为

会抛出错误,但脚本仍在以某种方式执行

./after-success.sh: 3: ./after-success.sh: function: not found
./after-success.sh: 4: printf: Illegal option -v
Warning: Permanently added '178.62.252.23' (ECDSA) to the list of known hosts.
From https://github.com/HTW-Projekt-2014-Commercetools/api
 * branch            master     -> FETCH_HEAD
... Git Log ...
Stopping Neeedo-API: ..done.
Starting Neeedo-API: ....done.
./after-success.sh: 6: ./after-success.sh: Syntax error: "}" unexpected
现在我有两个问题:

  • 为什么会抛出这些错误?如何使这个shell脚本尽可能独立于平台?我不知道哪个buildagent正在运行我的脚本,所以它应该在普通unix系统上运行

  • 如果无法确保travis构建失败,如何确保脚本返回不同于0的错误代码。目前,它仍然返回一个绿色构建,并且应用程序以某种方式启动,正如您在日志中看到的


  • (3.)有没有一种方法可以更好地格式化通过ssh发送的命令,而不是长字符串?

    将其更改为bash脚本。 第一行:#/bin/bash

    sh

    $  printf -v ___ %q "$1"
    sh: 1: printf: Illegal option -v
    
    $ printf -v ___ %q "$1"
    <no error>
    
    bash

    $  printf -v ___ %q "$1"
    sh: 1: printf: Illegal option -v
    
    $ printf -v ___ %q "$1"
    <no error>
    
    $printf-v\uuuq%q“$1”
    
    引发错误是因为远程主机上的
    /bin/sh
    无法理解
    函数
    关键字和
    -v
    printf参数

    将shebang行更改为
    #/bin/bash
    将修复这些错误

    即使有上述错误,脚本仍然“工作”的原因(引用,因为它没有真正工作,我不认为)是因为你运气好
    /bin/sh
    不理解
    函数
    关键字,因此它完全忽略了这一行,这意味着它可能直接运行ssh命令(而不是通过函数调用),并且没有正确使用
    $\uuu
    (因为
    printf-v
    错误)因此,没有运行正确的
    git checkout
    命令

    我本以为会看到一个错误,即不知道
    sshDeploy
    命令是什么,但可能它没有这样做,或者它被其他东西隐藏了

    尽管如此,这个功能根本没有真正的理由

    脚本的退出状态是上次运行的命令的退出状态,因此无需以
    exit$?
    结束

    有了这个功能,而没有这个功能,你的脚本就变成了

    codecov
    printf -v __ %q "$TRAVIS_COMMIT"
    ssh -oStrictHostKeyChecking=no deployuser@178.62.252.23 "cd api; git pull origin master; git checkout $__;./sbt clean; ./sbt stage; ./neeedo restart"
    

    您甚至可以避免使用
    printf-v
    ,因为git引用不太可能(如果不是不能的话)包含任何shell元字符,在这样的shell字符串中展开时需要转义(至少我相信)。虽然如果您不介意
    bash
    要求,这肯定更安全。

    谢谢,我会试试这个。关于我的第二个问题,你能给我一些建议吗?如何确保如果出现任何错误,我的脚本不会使用exitcode 0退出。是否有类似于“try catch”的内容?好吧,假设codecov命令将失败并返回127如果ssh返回0,我的脚本仍将返回0正确?如果是,那么我可能必须将返回值保存在变量中,然后使用这些变量的布尔运算或类似的操作退出。。。谢谢你的解释。是的,如果你想在任何简单的命令后失败,你可以使用
    set-e
    ,但是正确使用它会更困难,那么它听起来会很有用(尽管在简单的情况下可能很有用)。如果您想真正确定,最安全的方法是在每个命令失败后手动检查
    $?