如何解决在Alpine Linux中“伪terminal不会被分配,因为stdin不是terminal”?
我正在编写一个运行各种shell命令的PHP程序。 有时它需要调用su
,并通过devise,我希望提示提升特权密码。 在PHP中使用passthru()
可以正常工作。
我select了仅为我的程序编写functiontesting,因为它依赖于ssh
, su
和其他shell命令。 因此,我想在PHPUnit中运行真实的东西,看看它是否按我的预期工作。
由于这需要SSH服务器和用户帐户configuration,因此我已经设置了在Docker中运行的testing。 这种方法看起来会很好 – 图像生成,当它运行时调用PHPUnit,然后退出。 我希望有一种方法可以通过Docker将结果返回给Travis CI等调用系统。
我select了Alpine Linux作为我的基础Docker镜像,但是我遇到了terminal分配的问题。 我原本以为PHPUnit正在开发中(请参阅这个问题的原始版本),但现在我已经缩小到SSH,无论是由PHP运行,甚至只是在控制台。
这工作正常:
su -c whoami
但是,这并不是:
ssh localhost -t 'su -c whoami'
我得到:
苏:一定要起床才能正常工作
连接到本地主机closures。
请注意, ssh
设置为无密码访问本地主机(为了testing目的),所以我唯一希望input的密码是su
。
ssh
的手册build议-f
有助于要求input密码的位置(交换机“在命令执行前请求ssh进入背景”),所以我试试这个:
ssh localhost -t -f 'su -c whoami'
我得到:
伪terminal不会被分配,因为stdin不是terminal。
4275760bde94:〜$ su:必须是suid才能正常工作
啊,另一个错误! 好的,所以我尝试了这些想法 ,尤其是强迫terminal:
ssh localhost -tt -f 'su -c whoami'
双t仍然发出有关SUID的抱怨,仍然不起作用。
但是,如果我在我的Ubuntu开发机器上(也configurationPPK访问自己)这样做,它工作正常:
$ ssh localhost -t 'su -c whoami' Password: root Connection to localhost closed.
这使得它看起来像Alpine或BusyBox的OpenSSH是错误的。 我怎么能进一步深入这一点?
一个解决scheme只是交换到另一个基本的发行版,Ubuntu肯定会正常工作,但是这将大大增加我的Docker映像大小(目前总计68M)。 所以,如果可以的话,我想和阿尔派坚持一下。
不太可能是Docker
我确实想知道Docker是否可能阻止创build或连接terminal,但是很快就打了折扣,因为我可以通过docker exec -it container_name sh
获得交互式shell。 此外,我可以执行ssh
,然后在两个单独的命令在一个Dockershellsu
很好。
Bash没有帮助
我注意到Bash在Alpine中可用,但这也没有帮助,这让我感到惊讶:
/ $ apk add bash bash-4.3$ bash bash-4.3$ su nonpriv bash-4.3$ ssh localhost whoami nonpriv bash-4.3$ ssh localhost 'su -c whoami' su: must be suid to work properly bash-4.3$ ssh localhost 'su -s /bin/bash -c whoami' su: must be suid to work properly bash-4.3$ ssh -t localhost 'su -s /bin/bash -c whoami' su: must be suid to work properly Connection to localhost closed. bash-4.3$ ssh -tt localhost 'su -s /bin/bash -c whoami' su: must be suid to work properly Connection to localhost closed. bash-4.3$ ssh -tf localhost 'su -s /bin/bash -c whoami' Pseudo-terminal will not be allocated because stdin is not a terminal. bash-4.3$ su: must be suid to work properly bash-4.3$ ssh -ttf localhost 'su -s /bin/bash -c whoami' bash-4.3$ su: must be suid to work properly Connection to localhost closed.
尝试shell插值
我发现这近乎工作:
/ $ ssh -t localhost "$( su -c whoami )" sh: Password:: not found sh: root: not found Connection to localhost closed.
这使用标准的Alpine sh
shell,并使用前面提到的链接上find的"$()"
构造,而我并不完全理解它。 它输出Password:
,这是su
的提示,然后等待密码。 当input密码时,运行whoami
,它会打印root
。
所以它看起来像是运行命令,但我不知道是否立即运行whoami
,然后将其传递给ssh
(不是我想要的),或者它是否得到一个远程shell到本地然后再做(这是我的意图)。
在任何情况下,它都试图运行 stdout行,就像它们本身就是命令一样。 我怎样才能得到它只是通过SSH打印输出运行?
我猜我的问题是,这将在Ubuntu的容器,这certificate是正确的。 有趣的是,我仍然得到这个命令的“必须从terminal运行”的错误:
su -c whoami
但是不是在这里,一个terminal明确地分配给一个SSH无密码的命令给自己:
ssh -t localhost 'su -c whoami'
不幸的是,新的操作系统已经把我的68M图像碰到了430M,呃! 因此,我应该很高兴能够得到新的答案,使这项工作在阿尔卑斯山上。