why do bash behave differently for script from stdin?

Solution 1:

Short answer: there's an important difference between having bash read commands from a file, and having bash take all input from a file.

ssh tends to read all available input from standard input, and send it over the connection to the remote computer. When you run bash test.sh, the shell reads commands from test.sh, but standard input is still your terminal; ssh will send anything you've typed ahead to the true command (which will ignore it). When you run bash < test.sh, standard input is set to the script, so both bash and the commands it runs read from that. bash reads the if block, then executes it; ssh reads the rest of the script (the echo 2 command), and sends it to the remote true, which ignores it. bash then finds that it's at the end of its input, so it exits.