Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash:如何通过ssh发送我自己的自定义函数_Bash_Ssh Tunnel - Fatal编程技术网

Bash:如何通过ssh发送我自己的自定义函数

Bash:如何通过ssh发送我自己的自定义函数,bash,ssh-tunnel,Bash,Ssh Tunnel,我的目标是做到以下几点: 1) 检查特定服务器上每个GPU使用的内存量。我通过(nvidiasmi--querygpu=memory.free--format=csv)实现了这一点 2) 查找具有最大可用内存的GPU。我通过my_cmd()来实现这一点。它适用于我当前登录的远程服务器 3) 如果我登录的远程服务器上的最大可用内存小于1000 MiB,请通过SSH连接到集群中的其他GPU服务器以查找可用的最大可用内存。这些服务器根据进行标记以检查 我的最新一期: 当scriptuse被赋予cd命令

我的目标是做到以下几点:

1) 检查特定服务器上每个GPU使用的内存量。我通过
(nvidiasmi--querygpu=memory.free--format=csv)
实现了这一点

2) 查找具有最大可用内存的GPU。我通过
my_cmd()
来实现这一点。它适用于我当前登录的远程服务器

3) 如果我登录的远程服务器上的最大可用内存小于1000 MiB,请通过SSH连接到集群中的其他GPU服务器以查找可用的最大可用内存。这些服务器根据
进行标记以检查

我的最新一期:

scriptuse
被赋予
cd
命令等时,下面的代码工作

当给出
scriptuse
时,下面的代码失败
mycmd
。它给了我一个错误:

./test_run.sh: line 8: cd ~/spatial; echo : No such file or directory
1
bash: /my_script.sh: No such file or directory
2
bash: /my_script.sh: No such file or directory
3
bash: /my_script.sh: No such file or directory
4
bash: /my_script.sh: No such file or directory
bash:my\u cmd:command未找到

现在,我认为这里有不止一个问题。首先,我认为我没有正确地向
ssh
命令提供
my_cmd
。第二,当我使用
my_cmd
时,我认为我没有成功地登录到其他服务器

有人能指出什么地方出了问题以及如何解决吗

下面是完整的bash脚本

#/bin/bash

#https://stackoverflow.com/questions/45313313/nvidia-smi-command-in-bash-vs-in-terminal-for-maximum-of-an-array/45313404#45313404

my_cmd()
{
max_idx=0
max_mem=0
idx=0
{
  read _;                         # discard first line (header)
  while read -r mem _; do         # for each subsequent line, read first word into mem
    if (( mem > max_mem )); then  # compare against maximum mem value seen
      max_mem=$mem                # ...if greater, then update both that max value
      max_idx=$idx                # ...and our stored index value.
    fi
    ((++idx))
  done
} < <(nvidia-smi --query-gpu=memory.free --format=csv)
echo "Maximum memory seen is $max_mem, at processor $idx"
}

tocheck=('4' '5' '6' '7' '8')  #The GPUs to check
it1=1

#scriptuse="my_cmd" 
scriptuse= "cd ~/spatial; pwd; echo $gpuval"

while [ $it1 -lt ${#tocheck[@]} ] ; do #While we stil don't have enough free memory
        echo $it1 
        gpuval=${tocheck[$it1]}
        ssh gpu${gpuval} "${scriptuse}"
        it1=$[it1+1]
done
2) 创建一个单独的bash脚本,名为
my\u script.sh
,其中包含
my\u cmd

#/bin/bash

#https://stackoverflow.com/questions/45313313/nvidia-smi-command-in-bash-vs-in-terminal-for-maximum-of-an-array/45313404#45313404
max_idx=0
max_mem=0
idx=0
{
  read _;                         # discard first line (header)
  while read -r mem _; do         # for each subsequent line, read first word into mem
    if (( mem > max_mem )); then  # compare against maximum mem value seen
      max_mem=$mem                # ...if greater, then update both that max value
      max_idx=$idx                # ...and our stored index value.
    fi
    ((++idx))
  done
} < <(nvidia-smi --query-gpu=memory.free --format=csv)
echo "Maximum memory seen is $max_mem, at processor $idx"
编辑:最终解决方案

感谢下面被接受的答案和评论中的讨论,以下是最终有效的方法:

1) 将
my_script
保留为上一次编辑时的状态

2) 文件
test\u run
应如下所示:

#/bin/bash

#https://stackoverflow.com/questions/45313313/nvidia-smi-command-in-bash-vs-in-terminal-for-maximum-of-an-array/45313404#45313404

tocheck=('4' '5' '6' '7' '8')  #The GPUs to check
it1=1

scriptuse= "cd ~/spatial; echo $gpuval"

while [ $it1 -lt ${#tocheck[@]} ] ; do #While we stil don't have enough free memory
        echo $it1 
        gpuval=${tocheck[$it1]}
        ssh gpu${gpuval} "${scriptuse}" /my_script.sh
        it1=$[it1+1]
done   
#/bin/bash

tocheck=('4' '5' '6' '7' '8')  #The GPUs to check
it1=1

while [ $it1 -lt ${#tocheck[@]} ] ; do #While we still don't have enough free memory
        echo $it1 
        gpuval=${tocheck[$it1]}
        ssh gpu${gpuval} ~/spatial/my_script.sh
        it1=$[it1+1]
done

我认为这样做的原因是集群上的所有GPU都有一个公共存储,因此它们都可以访问
/user/spatial

脚本运行的环境(shell)与远程主机运行的环境(远程shell)完全无关。如果在shell中定义函数
my_cmd
,它将不会通过有线传输到远程主机的shell

尝试一个更简单的例子:

$ foo() { echo foo; }
$ foo
foo
$ ssh remote-host foo
bash: foo: command not found
# Copy the script to the remote host's /tmp directory
scp my_cmd.sh remote-host:/tmp
# Invoke the script on the remote host
$ ssh remote-host /tmp/my_cmd.sh
SSH、Bash和Linux/POSIX的设计并非如此。现在,
ssh
确实更新了远程环境的某些部分(如中所述),但这仅限于某些环境变量,而不是函数

值得注意的是,远程shell甚至可能与您的shell类型不同(例如,您的shell可能是Bash,但远程shell可能是Zsh),因此通常不可能跨
ssh
传输shell函数


一个更简单、更可靠的选择是创建一个shell脚本(而不是一个函数),您希望在远程shell上运行该脚本,并确保该脚本存在于远程计算机上。例如:

$ foo() { echo foo; }
$ foo
foo
$ ssh remote-host foo
bash: foo: command not found
# Copy the script to the remote host's /tmp directory
scp my_cmd.sh remote-host:/tmp
# Invoke the script on the remote host
$ ssh remote-host /tmp/my_cmd.sh

编辑:

您确定远程主机上存在
~/spatial

您确定远程主机上存在
/my_script.sh

同样,您的远程主机是一个完全不同的环境。文件或目录存在于本地计算机上并不意味着它存在于远程主机上,除非您将其放在那里


试试
ssh[remote host]'ls~'
ssh[remote host]'ls/'
-我打赌你会看到目录和文件不存在。

这看起来真的很迂回-为什么不把你需要的函数放在一个文件中,然后
scp
把文件放到远程服务器上呢?如果担心文件不同步,可以将文件签入VCS(Git、Mercurial)。“首先,我认为我没有正确地向ssh命令提供我的命令。”-更准确地说,你根本没有提供它-
ssh hostname foo
告诉远程服务器在其shell中调用
foo
命令,它不知道您的shell或其中定义的函数。@dim0414很抱歉,我不理解您的建议。当我使用注释外定义的
scriptuse
时,
ssh-gpu${gpuval}“${scriptuse}”
部分似乎正在工作。但是当我把它注释掉,并使用另一个
scriptuse
(“my_cmd”)时,它就不起作用了。对,因为远程服务器有一个
cd
命令。它不知道我的命令是什么。谢谢@dimo414,请查看我编辑的版本。问题还没有解决。@StatsSorceress我想你还没有把文件放到远程主机上。见我的编辑。嗨@dimo414。集群有一个中央存储器。集群中的每个GPU都可以看到我的所有文件。例如:
user@GPU4:~/spatial$ls
给出了
my\u script.sh test\u run.sh
这样做:
user@GPU1:~/spatial$ls
my\u script.sh test\u run.sh
您在那里的
ls
-ing目录是什么?大概是
~
,而不是
/
。您正在运行
/my\u script.sh
,但如果您将脚本放在当前目录中,则它是
/my\u script.sh
~/my\u script.sh
。我在输出中没有看到
spatial
目录。我正在
ls
调用
spatial
目录。我两个都试过了,有趣的是,我似乎根本就没有唱cd。第二个“~/my_script.sh”给了我这个:
bash:/user/my_script.sh:没有这样的文件或目录
,但它应该是
/user/spatial/
,而不仅仅是
/user
。这有意义吗?