| 1 | 
 | 
| 2 | ## compare_shells: bash dash mksh ash
 | 
| 3 | 
 | 
| 4 | # OSH mechanisms:
 | 
| 5 | #
 | 
| 6 | # - shopt -s strict_errexit 
 | 
| 7 | # - shopt -s command_sub_errexit
 | 
| 8 | # - inherit_errexit (bash)
 | 
| 9 | #
 | 
| 10 | # Summary:
 | 
| 11 | # - local assignment is different than global!  The exit code and errexit
 | 
| 12 | #   behavior are different because the concept of the "last command" is
 | 
| 13 | #   different.
 | 
| 14 | # - ash has copied bash behavior!
 | 
| 15 | 
 | 
| 16 | #### command sub: errexit is NOT inherited and outer shell keeps going
 | 
| 17 | 
 | 
| 18 | # This is the bash-specific bug here:
 | 
| 19 | # https://blogs.janestreet.com/when-bash-scripts-bite/
 | 
| 20 | # See inherit_errexit below.
 | 
| 21 | #
 | 
| 22 | # I remember finding a script that relies on bash's bad behavior, so OSH copies
 | 
| 23 | # it.  But you can opt in to better behavior.
 | 
| 24 | 
 | 
| 25 | set -o errexit
 | 
| 26 | echo $(echo one; false; echo two)  # bash/ash keep going
 | 
| 27 | echo parent status=$?
 | 
| 28 | ## STDOUT:
 | 
| 29 | one two
 | 
| 30 | parent status=0
 | 
| 31 | ## END
 | 
| 32 | # dash and mksh: inner shell aborts, but outer one keeps going!
 | 
| 33 | ## OK dash/mksh STDOUT:
 | 
| 34 | one
 | 
| 35 | parent status=0
 | 
| 36 | ## END
 | 
| 37 | 
 | 
| 38 | #### command sub with inherit_errexit only
 | 
| 39 | set -o errexit
 | 
| 40 | shopt -s inherit_errexit || true
 | 
| 41 | echo zero
 | 
| 42 | echo $(echo one; false; echo two)  # bash/ash keep going
 | 
| 43 | echo parent status=$?
 | 
| 44 | ## STDOUT:
 | 
| 45 | zero
 | 
| 46 | one
 | 
| 47 | parent status=0
 | 
| 48 | ## END
 | 
| 49 | ## N-I ash STDOUT:
 | 
| 50 | zero
 | 
| 51 | one two
 | 
| 52 | parent status=0
 | 
| 53 | ## END
 | 
| 54 | 
 | 
| 55 | #### strict_errexit and assignment builtins (local, export, readonly ...)
 | 
| 56 | set -o errexit
 | 
| 57 | shopt -s strict_errexit || true
 | 
| 58 | #shopt -s command_sub_errexit || true
 | 
| 59 | 
 | 
| 60 | f() {
 | 
| 61 |   local x=$(echo hi; false)
 | 
| 62 |   echo x=$x
 | 
| 63 | }
 | 
| 64 | 
 | 
| 65 | eval 'f'
 | 
| 66 | echo ---
 | 
| 67 | 
 | 
| 68 | ## status: 1
 | 
| 69 | ## STDOUT:
 | 
| 70 | ## END
 | 
| 71 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 72 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 73 | x=hi
 | 
| 74 | ---
 | 
| 75 | ## END
 | 
| 76 | 
 | 
| 77 | #### strict_errexit and command sub in export / readonly
 | 
| 78 | case $SH in (dash|bash|mksh|ash) exit ;; esac
 | 
| 79 | 
 | 
| 80 | $SH -o errexit -O strict_errexit -c 'echo a; export x=$(might-fail); echo b'
 | 
| 81 | echo status=$?
 | 
| 82 | $SH -o errexit -O strict_errexit -c 'echo a; readonly x=$(might-fail); echo b'
 | 
| 83 | echo status=$?
 | 
| 84 | $SH -o errexit -O strict_errexit -c 'echo a; x=$(true); echo b'
 | 
| 85 | echo status=$?
 | 
| 86 | 
 | 
| 87 | ## STDOUT:
 | 
| 88 | a
 | 
| 89 | status=1
 | 
| 90 | a
 | 
| 91 | status=1
 | 
| 92 | a
 | 
| 93 | b
 | 
| 94 | status=0
 | 
| 95 | ## END
 | 
| 96 | ## N-I dash/bash/mksh/ash stdout-json: ""
 | 
| 97 | 
 | 
| 98 | 
 | 
| 99 | #### strict_errexit disallows pipeline
 | 
| 100 | set -o errexit
 | 
| 101 | shopt -s strict_errexit || true
 | 
| 102 | 
 | 
| 103 | if echo 1 | grep 1; then
 | 
| 104 |   echo one
 | 
| 105 | fi
 | 
| 106 | 
 | 
| 107 | ## status: 1
 | 
| 108 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 109 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 110 | 1
 | 
| 111 | one
 | 
| 112 | ## END
 | 
| 113 | 
 | 
| 114 | #### strict_errexit allows singleton pipeline
 | 
| 115 | set -o errexit
 | 
| 116 | shopt -s strict_errexit || true
 | 
| 117 | 
 | 
| 118 | if ! false; then
 | 
| 119 |   echo yes
 | 
| 120 | fi
 | 
| 121 | 
 | 
| 122 | ## STDOUT:
 | 
| 123 | yes
 | 
| 124 | ## END
 | 
| 125 | 
 | 
| 126 | #### strict_errexit without errexit proc
 | 
| 127 | myproc() {
 | 
| 128 |   echo myproc
 | 
| 129 | }
 | 
| 130 | myproc || true
 | 
| 131 | 
 | 
| 132 | # This should be a no-op I guess
 | 
| 133 | shopt -s strict_errexit || true
 | 
| 134 | myproc || true
 | 
| 135 | 
 | 
| 136 | ## status: 1
 | 
| 137 | ## STDOUT:
 | 
| 138 | myproc
 | 
| 139 | ## END
 | 
| 140 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 141 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 142 | myproc
 | 
| 143 | myproc
 | 
| 144 | ## END
 | 
| 145 | 
 | 
| 146 | #### strict_errexit without errexit proc / command sub
 | 
| 147 | 
 | 
| 148 | # Implementation quirk:
 | 
| 149 | # - The proc check happens only if errexit WAS on and is disabled
 | 
| 150 | # - But 'shopt --unset allow_csub_psub' happens if it was never on
 | 
| 151 | 
 | 
| 152 | shopt -s strict_errexit || true
 | 
| 153 | 
 | 
| 154 | p() {
 | 
| 155 |   echo before
 | 
| 156 |   local x
 | 
| 157 |   # This line fails, which is a bit weird, but errexit
 | 
| 158 |   x=$(false)
 | 
| 159 |   echo x=$x
 | 
| 160 | }
 | 
| 161 | 
 | 
| 162 | if p; then
 | 
| 163 |   echo ok
 | 
| 164 | fi
 | 
| 165 | 
 | 
| 166 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 167 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 168 | before
 | 
| 169 | x=
 | 
| 170 | ok
 | 
| 171 | ## END
 | 
| 172 | ## status: 1
 | 
| 173 | ## STDOUT:
 | 
| 174 | ## END
 | 
| 175 | 
 | 
| 176 | #### strict_errexit and errexit disabled
 | 
| 177 | case $SH in (dash|bash|mksh|ash) exit ;; esac
 | 
| 178 | 
 | 
| 179 | shopt -s parse_brace strict_errexit || true
 | 
| 180 | 
 | 
| 181 | p() {
 | 
| 182 |   echo before
 | 
| 183 |   local x
 | 
| 184 |   # This line fails, which is a bit weird, but errexit
 | 
| 185 |   x=$(false)
 | 
| 186 |   echo x=$x
 | 
| 187 | }
 | 
| 188 | 
 | 
| 189 | set -o errexit
 | 
| 190 | shopt --unset errexit {
 | 
| 191 |   # It runs normally here, because errexit was disabled (just not by a
 | 
| 192 |   # conditional)
 | 
| 193 |   p
 | 
| 194 | }
 | 
| 195 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 196 | ## END
 | 
| 197 | ## STDOUT:
 | 
| 198 | before
 | 
| 199 | x=
 | 
| 200 | ## END
 | 
| 201 | 
 | 
| 202 | 
 | 
| 203 | #### command sub with command_sub_errexit only
 | 
| 204 | set -o errexit
 | 
| 205 | shopt -s command_sub_errexit || true
 | 
| 206 | echo zero
 | 
| 207 | echo $(echo one; false; echo two)  # bash/ash keep going
 | 
| 208 | echo parent status=$?
 | 
| 209 | ## STDOUT:
 | 
| 210 | zero
 | 
| 211 | one two
 | 
| 212 | parent status=0
 | 
| 213 | ## END
 | 
| 214 | ## N-I dash/mksh STDOUT:
 | 
| 215 | zero
 | 
| 216 | one
 | 
| 217 | parent status=0
 | 
| 218 | ## END
 | 
| 219 | 
 | 
| 220 | #### command_sub_errexit stops at first error
 | 
| 221 | case $SH in (dash|bash|mksh|ash) exit ;; esac
 | 
| 222 | 
 | 
| 223 | set -o errexit
 | 
| 224 | shopt --set parse_brace command_sub_errexit verbose_errexit || true
 | 
| 225 | 
 | 
| 226 | rm -f BAD
 | 
| 227 | 
 | 
| 228 | try {
 | 
| 229 |   echo $(date %d) $(touch BAD)
 | 
| 230 | }
 | 
| 231 | if ! test -f BAD; then  # should not exist
 | 
| 232 |   echo OK
 | 
| 233 | fi
 | 
| 234 | 
 | 
| 235 | ## STDOUT:
 | 
| 236 | OK
 | 
| 237 | ## END
 | 
| 238 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 239 | ## END
 | 
| 240 | 
 | 
| 241 | #### command sub with inherit_errexit and command_sub_errexit
 | 
| 242 | set -o errexit
 | 
| 243 | 
 | 
| 244 | # bash implements inherit_errexit, but it's not as strict as OSH.
 | 
| 245 | shopt -s inherit_errexit || true
 | 
| 246 | shopt -s command_sub_errexit || true
 | 
| 247 | echo zero
 | 
| 248 | echo $(echo one; false; echo two)  # bash/ash keep going
 | 
| 249 | echo parent status=$?
 | 
| 250 | ## STDOUT:
 | 
| 251 | zero
 | 
| 252 | ## END
 | 
| 253 | ## status: 1
 | 
| 254 | ## N-I dash/mksh/bash status: 0
 | 
| 255 | ## N-I dash/mksh/bash STDOUT:
 | 
| 256 | zero
 | 
| 257 | one
 | 
| 258 | parent status=0
 | 
| 259 | ## END
 | 
| 260 | ## N-I ash status: 0
 | 
| 261 | ## N-I ash STDOUT:
 | 
| 262 | zero
 | 
| 263 | one two
 | 
| 264 | parent status=0
 | 
| 265 | ## END
 | 
| 266 | 
 | 
| 267 | #### command sub: last command fails but keeps going and exit code is 0
 | 
| 268 | set -o errexit
 | 
| 269 | echo $(echo one; false)  # we lost the exit code
 | 
| 270 | echo status=$?
 | 
| 271 | ## STDOUT:
 | 
| 272 | one
 | 
| 273 | status=0
 | 
| 274 | ## END
 | 
| 275 | 
 | 
| 276 | #### global assignment with command sub: middle command fails
 | 
| 277 | set -o errexit
 | 
| 278 | s=$(echo one; false; echo two;)
 | 
| 279 | echo "$s"
 | 
| 280 | ## status: 0
 | 
| 281 | ## STDOUT:
 | 
| 282 | one
 | 
| 283 | two
 | 
| 284 | ## END
 | 
| 285 | # dash and mksh: whole thing aborts!
 | 
| 286 | ## OK dash/mksh stdout-json: ""
 | 
| 287 | ## OK dash/mksh status: 1
 | 
| 288 | 
 | 
| 289 | #### global assignment with command sub: last command fails and it aborts
 | 
| 290 | set -o errexit
 | 
| 291 | s=$(echo one; false)
 | 
| 292 | echo status=$?
 | 
| 293 | ## stdout-json: ""
 | 
| 294 | ## status: 1
 | 
| 295 | 
 | 
| 296 | #### local: middle command fails and keeps going
 | 
| 297 | set -o errexit
 | 
| 298 | f() {
 | 
| 299 |   echo good
 | 
| 300 |   local x=$(echo one; false; echo two)
 | 
| 301 |   echo status=$?
 | 
| 302 |   echo $x
 | 
| 303 | }
 | 
| 304 | f
 | 
| 305 | ## STDOUT:
 | 
| 306 | good
 | 
| 307 | status=0
 | 
| 308 | one two
 | 
| 309 | ## END
 | 
| 310 | # for dash and mksh, the INNER shell aborts, but the outer one keeps going!
 | 
| 311 | ## OK dash/mksh STDOUT:
 | 
| 312 | good
 | 
| 313 | status=0
 | 
| 314 | one
 | 
| 315 | ## END
 | 
| 316 | 
 | 
| 317 | #### local: last command fails and also keeps going
 | 
| 318 | set -o errexit
 | 
| 319 | f() {
 | 
| 320 |   echo good
 | 
| 321 |   local x=$(echo one; false)
 | 
| 322 |   echo status=$?
 | 
| 323 |   echo $x
 | 
| 324 | }
 | 
| 325 | f
 | 
| 326 | ## STDOUT:
 | 
| 327 | good
 | 
| 328 | status=0
 | 
| 329 | one
 | 
| 330 | ## END
 | 
| 331 | 
 | 
| 332 | #### local and inherit_errexit / command_sub_errexit
 | 
| 333 | # I've run into this problem a lot.
 | 
| 334 | set -o errexit
 | 
| 335 | shopt -s inherit_errexit || true  # bash option
 | 
| 336 | shopt -s command_sub_errexit || true  # oil option
 | 
| 337 | f() {
 | 
| 338 |   echo good
 | 
| 339 |   local x=$(echo one; false; echo two)
 | 
| 340 |   echo status=$?
 | 
| 341 |   echo $x
 | 
| 342 | }
 | 
| 343 | f
 | 
| 344 | ## status: 1
 | 
| 345 | ## STDOUT:
 | 
| 346 | good
 | 
| 347 | ## END
 | 
| 348 | ## N-I ash status: 0
 | 
| 349 | ## N-I ash STDOUT:
 | 
| 350 | good
 | 
| 351 | status=0
 | 
| 352 | one two
 | 
| 353 | ## END
 | 
| 354 | ## N-I bash/dash/mksh status: 0
 | 
| 355 | ## N-I bash/dash/mksh STDOUT:
 | 
| 356 | good
 | 
| 357 | status=0
 | 
| 358 | one
 | 
| 359 | ## END
 | 
| 360 | 
 | 
| 361 | #### global assignment when last status is failure
 | 
| 362 | # this is a bug I introduced
 | 
| 363 | set -o errexit
 | 
| 364 | x=$(false) || true   # from abuild
 | 
| 365 | [ -n "$APORTSDIR" ] && true
 | 
| 366 | BUILDDIR=${_BUILDDIR-$BUILDDIR}
 | 
| 367 | echo status=$?
 | 
| 368 | ## STDOUT:
 | 
| 369 | status=0
 | 
| 370 | ## END
 | 
| 371 | 
 | 
| 372 | #### strict_errexit prevents errexit from being disabled in function
 | 
| 373 | set -o errexit
 | 
| 374 | fun() { echo fun; }
 | 
| 375 | 
 | 
| 376 | fun || true  # this is OK
 | 
| 377 | 
 | 
| 378 | shopt -s strict_errexit || true
 | 
| 379 | 
 | 
| 380 | echo 'builtin ok' || true
 | 
| 381 | env echo 'external ok' || true
 | 
| 382 | 
 | 
| 383 | fun || true  # this fails
 | 
| 384 | 
 | 
| 385 | ## status: 1
 | 
| 386 | ## STDOUT:
 | 
| 387 | fun
 | 
| 388 | builtin ok
 | 
| 389 | external ok
 | 
| 390 | ## END
 | 
| 391 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 392 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 393 | fun
 | 
| 394 | builtin ok
 | 
| 395 | external ok
 | 
| 396 | fun
 | 
| 397 | ## END
 | 
| 398 | 
 | 
| 399 | #### strict_errexit prevents errexit from being disabled in brace group
 | 
| 400 | set -o errexit
 | 
| 401 | # false failure is NOT respected either way
 | 
| 402 | { echo foo; false; echo bar; } || echo "failed"
 | 
| 403 | 
 | 
| 404 | shopt -s strict_errexit || true
 | 
| 405 | { echo foo; false; echo bar; } || echo "failed"
 | 
| 406 | ## status: 1
 | 
| 407 | ## STDOUT:
 | 
| 408 | foo
 | 
| 409 | bar
 | 
| 410 | ## END
 | 
| 411 | 
 | 
| 412 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 413 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 414 | foo
 | 
| 415 | bar
 | 
| 416 | foo
 | 
| 417 | bar
 | 
| 418 | ## END
 | 
| 419 | 
 | 
| 420 | #### strict_errexit prevents errexit from being disabled in subshell
 | 
| 421 | set -o errexit
 | 
| 422 | shopt -s inherit_errexit || true
 | 
| 423 | 
 | 
| 424 | # false failure is NOT respected either way
 | 
| 425 | ( echo foo; false; echo bar; ) || echo "failed"
 | 
| 426 | 
 | 
| 427 | shopt -s strict_errexit || true
 | 
| 428 | ( echo foo; false; echo bar; ) || echo "failed"
 | 
| 429 | ## status: 1
 | 
| 430 | ## STDOUT:
 | 
| 431 | foo
 | 
| 432 | bar
 | 
| 433 | ## END
 | 
| 434 | 
 | 
| 435 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 436 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 437 | foo
 | 
| 438 | bar
 | 
| 439 | foo
 | 
| 440 | bar
 | 
| 441 | ## END
 | 
| 442 | 
 | 
| 443 | #### strict_errexit and ! && || if while until
 | 
| 444 | prelude='set -o errexit
 | 
| 445 | shopt -s strict_errexit || true
 | 
| 446 | fun() { echo fun; }'
 | 
| 447 | 
 | 
| 448 | $SH -c "$prelude; ! fun; echo 'should not get here'"
 | 
| 449 | echo bang=$?
 | 
| 450 | echo --
 | 
| 451 | 
 | 
| 452 | $SH -c "$prelude; fun || true"
 | 
| 453 | echo or=$?
 | 
| 454 | echo --
 | 
| 455 | 
 | 
| 456 | $SH -c "$prelude; fun && true"
 | 
| 457 | echo and=$?
 | 
| 458 | echo --
 | 
| 459 | 
 | 
| 460 | $SH -c "$prelude; if fun; then true; fi"
 | 
| 461 | echo if=$?
 | 
| 462 | echo --
 | 
| 463 | 
 | 
| 464 | $SH -c "$prelude; while fun; do echo while; exit; done"
 | 
| 465 | echo while=$?
 | 
| 466 | echo --
 | 
| 467 | 
 | 
| 468 | $SH -c "$prelude; until fun; do echo until; exit; done"
 | 
| 469 | echo until=$?
 | 
| 470 | echo --
 | 
| 471 | 
 | 
| 472 | 
 | 
| 473 | ## STDOUT:
 | 
| 474 | bang=1
 | 
| 475 | --
 | 
| 476 | or=1
 | 
| 477 | --
 | 
| 478 | and=1
 | 
| 479 | --
 | 
| 480 | if=1
 | 
| 481 | --
 | 
| 482 | while=1
 | 
| 483 | --
 | 
| 484 | until=1
 | 
| 485 | --
 | 
| 486 | ## END
 | 
| 487 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 488 | fun
 | 
| 489 | should not get here
 | 
| 490 | bang=0
 | 
| 491 | --
 | 
| 492 | fun
 | 
| 493 | or=0
 | 
| 494 | --
 | 
| 495 | fun
 | 
| 496 | and=0
 | 
| 497 | --
 | 
| 498 | fun
 | 
| 499 | if=0
 | 
| 500 | --
 | 
| 501 | fun
 | 
| 502 | while
 | 
| 503 | while=0
 | 
| 504 | --
 | 
| 505 | fun
 | 
| 506 | until=0
 | 
| 507 | --
 | 
| 508 | ## END
 | 
| 509 | 
 | 
| 510 | #### if pipeline doesn't fail fatally
 | 
| 511 | set -o errexit
 | 
| 512 | set -o pipefail
 | 
| 513 | 
 | 
| 514 | f() {
 | 
| 515 |   local dir=$1
 | 
| 516 | 	if ls $dir | grep ''; then
 | 
| 517 |     echo foo
 | 
| 518 | 		echo ${PIPESTATUS[@]}
 | 
| 519 | 	fi
 | 
| 520 | }
 | 
| 521 | rmdir $TMP/_tmp || true
 | 
| 522 | rm -f $TMP/*
 | 
| 523 | f $TMP
 | 
| 524 | f /nonexistent # should fail
 | 
| 525 | echo done
 | 
| 526 | 
 | 
| 527 | ## N-I dash status: 2
 | 
| 528 | ## N-I dash stdout-json: ""
 | 
| 529 | ## STDOUT:
 | 
| 530 | done
 | 
| 531 | ## END
 | 
| 532 | 
 | 
| 533 | #### errexit is silent (verbose_errexit for Oil)
 | 
| 534 | shopt -u verbose_errexit 2>/dev/null || true
 | 
| 535 | set -e
 | 
| 536 | false
 | 
| 537 | ## stderr-json: ""
 | 
| 538 | ## status: 1
 | 
| 539 | 
 | 
| 540 | #### command sub errexit preserves exit code
 | 
| 541 | set -e
 | 
| 542 | shopt -s command_sub_errexit || true
 | 
| 543 | 
 | 
| 544 | echo before
 | 
| 545 | echo $(exit 42)
 | 
| 546 | echo after
 | 
| 547 | ## STDOUT:
 | 
| 548 | before
 | 
| 549 | ## END
 | 
| 550 | ## status: 42
 | 
| 551 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 552 | before
 | 
| 553 | 
 | 
| 554 | after
 | 
| 555 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 556 | 
 | 
| 557 | #### What's in strict:all?
 | 
| 558 | 
 | 
| 559 | # inherit_errexit, strict_errexit, but not command_sub_errexit!
 | 
| 560 | # for that you need oil:upgrade!
 | 
| 561 | 
 | 
| 562 | set -o errexit
 | 
| 563 | shopt -s strict:all || true
 | 
| 564 | 
 | 
| 565 | # inherit_errexit is bash compatible, so we have it
 | 
| 566 | #echo $(date %x)
 | 
| 567 | 
 | 
| 568 | # command_sub_errexit would hide errors!
 | 
| 569 | f() {
 | 
| 570 |   local d=$(date %x)
 | 
| 571 | }
 | 
| 572 | f
 | 
| 573 | 
 | 
| 574 | deploy_func() {
 | 
| 575 |   echo one
 | 
| 576 |   false
 | 
| 577 |   echo two
 | 
| 578 | }
 | 
| 579 | 
 | 
| 580 | if ! deploy_func; then
 | 
| 581 |   echo failed
 | 
| 582 | fi
 | 
| 583 | 
 | 
| 584 | echo 'should not get here'
 | 
| 585 | 
 | 
| 586 | ## status: 1
 | 
| 587 | ## STDOUT:
 | 
| 588 | ## END
 | 
| 589 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 590 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 591 | one
 | 
| 592 | two
 | 
| 593 | should not get here
 | 
| 594 | ## END
 | 
| 595 | 
 | 
| 596 | #### command_sub_errexit causes local d=$(date %x) to fail
 | 
| 597 | set -o errexit
 | 
| 598 | shopt -s inherit_errexit || true
 | 
| 599 | #shopt -s strict_errexit || true
 | 
| 600 | shopt -s command_sub_errexit || true
 | 
| 601 | 
 | 
| 602 | myproc() {
 | 
| 603 |   # this is disallowed because we want a runtime error 100% of the time
 | 
| 604 |   local x=$(true)
 | 
| 605 | 
 | 
| 606 |   # Realistic example.  Should fail here but shells don't!
 | 
| 607 |   local d=$(date %x)
 | 
| 608 |   echo hi
 | 
| 609 | }
 | 
| 610 | myproc
 | 
| 611 | 
 | 
| 612 | ## status: 1
 | 
| 613 | ## STDOUT:
 | 
| 614 | ## END
 | 
| 615 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 616 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 617 | hi
 | 
| 618 | ## END
 | 
| 619 | 
 | 
| 620 | #### command_sub_errexit and command sub in array
 | 
| 621 | case $SH in (dash|ash|mksh) exit ;; esac
 | 
| 622 | 
 | 
| 623 | set -o errexit
 | 
| 624 | shopt -s inherit_errexit || true
 | 
| 625 | #shopt -s strict_errexit || true
 | 
| 626 | shopt -s command_sub_errexit || true
 | 
| 627 | 
 | 
| 628 | # We don't want silent failure here
 | 
| 629 | readonly -a myarray=( one "$(date %x)" two )
 | 
| 630 | 
 | 
| 631 | #echo len=${#myarray[@]}
 | 
| 632 | argv.py "${myarray[@]}"
 | 
| 633 | ## status: 1
 | 
| 634 | ## STDOUT:
 | 
| 635 | ## END
 | 
| 636 | ## N-I bash status: 0
 | 
| 637 | ## N-I bash STDOUT:
 | 
| 638 | ['one', '', 'two']
 | 
| 639 | ## END
 | 
| 640 | ## N-I dash/ash/mksh status: 0
 | 
| 641 | 
 | 
| 642 | #### OLD: command sub in conditional, with inherit_errexit
 | 
| 643 | set -o errexit
 | 
| 644 | shopt -s inherit_errexit || true
 | 
| 645 | if echo $(echo 1; false; echo 2); then
 | 
| 646 |   echo A
 | 
| 647 | fi
 | 
| 648 | echo done
 | 
| 649 | 
 | 
| 650 | ## STDOUT:
 | 
| 651 | 1 2
 | 
| 652 | A
 | 
| 653 | done
 | 
| 654 | ## END
 | 
| 655 | ## N-I dash/mksh STDOUT:
 | 
| 656 | 1
 | 
| 657 | A
 | 
| 658 | done
 | 
| 659 | ## END
 | 
| 660 | 
 | 
| 661 | #### OLD: command sub in redirect in conditional
 | 
| 662 | set -o errexit
 | 
| 663 | 
 | 
| 664 | if echo tmp_contents > $(echo tmp); then
 | 
| 665 |   echo 2
 | 
| 666 | fi
 | 
| 667 | cat tmp
 | 
| 668 | ## STDOUT:
 | 
| 669 | 2
 | 
| 670 | tmp_contents
 | 
| 671 | ## END
 | 
| 672 | 
 | 
| 673 | #### Regression
 | 
| 674 | case $SH in (bash|dash|ash|mksh) exit ;; esac
 | 
| 675 | 
 | 
| 676 | shopt --set oil:upgrade
 | 
| 677 | 
 | 
| 678 | shopt --unset errexit {
 | 
| 679 |   echo hi
 | 
| 680 | }
 | 
| 681 | 
 | 
| 682 | proc p {
 | 
| 683 |   echo p
 | 
| 684 | }
 | 
| 685 | 
 | 
| 686 | shopt --unset errexit {
 | 
| 687 |   p
 | 
| 688 | }
 | 
| 689 | ## STDOUT:
 | 
| 690 | hi
 | 
| 691 | p
 | 
| 692 | ## END
 | 
| 693 | ## N-I bash/dash/ash/mksh stdout-json: ""
 | 
| 694 | 
 | 
| 695 | #### ShAssignment used as conditional
 | 
| 696 | 
 | 
| 697 | while x=$(false)
 | 
| 698 | do   
 | 
| 699 |   echo while
 | 
| 700 | done
 | 
| 701 | 
 | 
| 702 | if x=$(false)
 | 
| 703 | then
 | 
| 704 |   echo if
 | 
| 705 | fi
 | 
| 706 | 
 | 
| 707 | if x=$(true)
 | 
| 708 | then
 | 
| 709 |   echo yes
 | 
| 710 | fi
 | 
| 711 | 
 | 
| 712 | # Same thing with errexit -- NOT affected
 | 
| 713 | set -o errexit
 | 
| 714 | 
 | 
| 715 | while x=$(false)
 | 
| 716 | do   
 | 
| 717 |   echo while
 | 
| 718 | done
 | 
| 719 | 
 | 
| 720 | if x=$(false)
 | 
| 721 | then
 | 
| 722 |   echo if
 | 
| 723 | fi
 | 
| 724 | 
 | 
| 725 | if x=$(true)
 | 
| 726 | then
 | 
| 727 |   echo yes
 | 
| 728 | fi
 | 
| 729 | 
 | 
| 730 | # Same thing with strict_errexit -- NOT affected
 | 
| 731 | shopt -s strict_errexit || true
 | 
| 732 | 
 | 
| 733 | while x=$(false)
 | 
| 734 | do   
 | 
| 735 |   echo while
 | 
| 736 | done
 | 
| 737 | 
 | 
| 738 | if x=$(false)
 | 
| 739 | then
 | 
| 740 |   echo if
 | 
| 741 | fi
 | 
| 742 | 
 | 
| 743 | if x=$(true)
 | 
| 744 | then
 | 
| 745 |   echo yes
 | 
| 746 | fi
 | 
| 747 | 
 | 
| 748 | ## status: 1
 | 
| 749 | ## STDOUT:
 | 
| 750 | yes
 | 
| 751 | yes
 | 
| 752 | ## END
 | 
| 753 | ## N-I dash/bash/mksh/ash status: 0
 | 
| 754 | ## N-I dash/bash/mksh/ash STDOUT:
 | 
| 755 | yes
 | 
| 756 | yes
 | 
| 757 | yes
 | 
| 758 | ## END
 |