Я думаю, что проблема в том, что здесь задействованы три оболочки:
- локальная оболочка, которая обрабатывает команду
ssh ;
- удаленная оболочка, которую
ssh вызывает для обработки команды на целевом хосте;
- дополнительная оболочка, вызываемая
sh -c в удаленной команде.
Цитаты делают две вещи:
- они останавливают локальную оболочку, вычисляя любые переменные в локальной оболочке (1);
- они проверяют наличие единственного параметра для удаленного
sh -c .
Таким образом, ssh видит четыре параметра: user@host , sh , -c и требуемую команду. Однако кавычки удаляются при построении четвертого параметра, и когда удаленная оболочка (2) получает свои параметры, она интерпретирует сам $(false) , и код завершения устанавливается в его собственной среде перед вызовом subshell (3).
Таким образом, дополнительная оболочка (3) видит DIR= && echo ok || echo fail и DIR= - абсолютно корректная, безошибочная команда, поэтому ветка ok .
Вы можете увидеть тот же эффект в:
sh -c 'sh -c "DIR=$(false) && echo ok || echo not"'
или же:
sh -c "sh -c 'DIR=$(false) && echo ok || echo not'"
В обоих случаях он работает "правильно", если вы поставите \ перед $ , так как это останавливает расширение второй оболочки $(false) во второй оболочке. Я использовал двойные кавычки, чтобы сделать механизмы более понятными - если вы предпочитаете, есть довольно извилистые:
sh -c 'sh -c '\''DIR=$(false) && echo ok || echo not'\'
Пример Ричарда работает, потому что все раскрытие выполняется в единственной удаленной оболочке, и первоначальное false; не влияет на последующую команду. Это не имеет ничего общего с темой, обсуждаемой в его ссылке.