如何将文件复制到没有权限的用户的远程服务器?



当我需要使用具有足够权限的用户通过 SSH 将文件从本地服务器(服务器 A(复制到远程服务器(服务器 B(时,我成功地做到了这一点,如下所示

localpath='/this/is/local/path/file1.txt'
remotepath='/this/is/remote/path/'
mypass='MyPassword123'
sshpass -p $mypass scp username@hostname:$localpath $remotepath

现在,我必须使用没有足够的复制权限的用户将文件从服务器 A 传输到服务器 C。然后一次 我连接到服务器C,我需要发送su才能发送cdls等命令。

手动,我通过SSH访问服务器C,如下所示:

[root@ServerA ~]# ssh username@hostname
You are trying to access a restricted zone. Only Authorized Users allowed.
Password: 
Last login: Sat Jun 13 10:17:40 2020 from XXX.XXX.XXX.XXX
ServerC ~ $ 
ServerC ~ $ su
Password:
ServerC /home/myuser # 
ServerC /home/myuser # cd /documents/backups/
ServerC /documents/backups # 

此时myuser拥有超级用户权限,我可以发送命令。

那么,如何自动执行将文件从服务器 A 复制到服务器 C 的任务,并在连接到服务器 C 后发送su

到目前为止,我已经尝试过这样做:

sshpass -p $mypass ssh -t username@hostname "su -c "cd /documents/backups/ && ls""

它请求su的密码,我能够发送cdls但是使用此命令,我不会将文件从服务器 A 复制到服务器 C,只是半自动访问服务器 C 并在服务器 C 中发送su

提前感谢任何帮助。

更新

# $TAR | ssh $username@$hostname "$COMMAND"
+ tar -cv -C /this/is/local/path/file1.txt .
+ ssh username@X.X.X.X 'set -x; rm -f /tmp/copy && mknod /tmp/copy p; su - <<< "su_password
set -x; tar -xv -C /this/is/remote/path/ . < /tmp/copy" & cat > /tmp/copy'
tar: /this/is/local/path/file1.txt: Cannot chdir: Not a directory
tar: Error is not recoverable: exiting now
You are trying to access a restricted zone. Only Authorized Users allowed.
Password:
+ rm -f /tmp/copy
+ mknod /tmp/copy p
+ su -
+ cat
Password:

编者按:本答案的先前版本使用sudo,当前版本根据问题中的要求使用su


您可以使用tar和管道,如下所示:

TAR="tar -cv -C $localpath ."
UNTAR="tar -xv -C $remotepath ."
PREPARE_PIPE="rm -f /tmp/copy && mknod /tmp/copy p"
NEWLINE=$'n' # that's the easiest way to get a literal newline
ROOT_PASSWORD=rootpasswordverydangerous
COMMAND="set -x; $PREPARE_PIPE; su - <<< "${ROOT_PASSWORD}${NEWLINE} set -x; $UNTAR < /tmp/copy" & cat > /tmp/copy"
$TAR | ssh username@hostname "$COMMAND"

解释:

tar -c .将当前目录存档到单个文件中。我们不会将-f传递给tar,因此单个文件是标准输出。

tar -x .将单个 tar 存档文件的内容提取到当前目录。我们不会将-f传递给tar,因此单个文件是标准输入。

-C <path>告诉tarcd<path>中,以便它将成为从/复制到文件的当前目录。

-v只是告诉 tar 列出 tar 存档/提取的文件,用于调试目的。

同样,set -x只是为了调试目的而发出跟踪信息的bash

因此,我们将$localpath存档到 stdout 中,并将其管道传输到ssh,这会将其管道传输到$COMMAND

如果有一种方法可以在命令行中给su密码,我们会使用类似的东西:

$TAR | ssh ... su --password ${ROOT_PASSWORD} -c "$UNTAR"

事情本来会很简单。

su没有。su像贝壳一样运行,从标准中读取。因此,它将首先读取密码,一旦读取密码并且su建立了根会话,它就会从 stdin读取命令。这就是为什么我们有su - <<< "${ROOT_PASSWORD}${NEWLINE}${UNTAR}.

但是现在 stdin 由密码和命令使用,所以我们不能将其用作存档。我们可以使用另一个文件描述符,但我不想这样做,因为这样解决方案可以更容易地移植到sudo而不是susudo关闭所有文件描述符,sudo -C 200(仅关闭 200 以上的文件描述符(可能不起作用(在我的测试计算机上不起作用(。

如果我们朝这个方向走,我们会使用类似的东西

$TAR | ssh ... 'exec 9<&2 && sudo -S <<< $mypass bash -c "$UNTAR <&9"'

我们的下一个选择是执行类似cat > /tmp/archive.tar的操作,以便将整个存档写入文件,然后具有类似$UNTAR < /tmp/archive.tar.但是存档可能很大,我们可能会用完磁盘空间。

所以这个想法是创建一个专用管道 - 这PREPARE_PIPE.管道不会将任何内容保存到磁盘,也不会将整个流存储在内存中,因此读取器和写入器必须同时工作(你知道,就像使用真正的管道一样(。

因此,从$ROOT_PASSWORD重定向su的 stdin,我们用cat > /tmp/copyssh的 stdin 拉入我们的管道中,并并行(&(从管道中读取$UNTAR(< /tmp/copy(。

笔记:

  • 如果网络速度太慢,您还可以将-z传递给两个tar命令以压缩传递它。
  • tar将保留源的元数据,例如时间戳和所有权。
  • $ROOT_PASSWORD传递给命令不是很好的做法,任何运行ps -ef的人都可以看到密码。有一些方法可以更安全地将密码传递给服务器 C,我没有包含它,以免使这个答案进一步复杂化。
  • 我建议要求服务器的所有者安装sudo,这样如果密码通过ps -ef泄露,至少它不是root密码。

相关内容

  • 没有找到相关文章

最新更新