简体   繁体   English

如何在 BATS 测试中激活 Bash function 中的 ssh 帐户?

[英]How to activate an ssh-account in Bash function in BATS test?

Context语境

As part of a Bash script that is tested using the BATS, I noticed that my tests are not terminated when I run a function that activates an ssh-account.作为使用 BATS 测试的 Bash 脚本的一部分,我注意到当我运行激活 ssh 帐户的 function 时,我的测试并未终止。

Code代码

The following function assumes a private and public ssh key pair exists in /home/<username>/.ssh/ .以下 function 假定 /home/<username>/.ssh/ 中存在私有和公共/home/<username>/.ssh/密钥对。 If I run it manually using source src/the_bash_script.sh && activate_ssh_account <my_git_username> , it works and says Identity added: /home/name/.ssh/<my_git_email> :如果我使用source src/the_bash_script.sh && activate_ssh_account <my_git_username>手动运行它,它可以工作并Identity added: /home/name/.ssh/<my_git_email>

#!/bin/bash
# Activates/enables the ssh for 
activate_ssh_account() {
    git_username=$1
    eval "$(ssh-agent -s)"
    ssh-add ~/.ssh/"$git_username"
}

However, when it is ran from the test with:但是,当它从测试中运行时:

#!./test/libs/bats/bin/bats
load 'libs/bats-support/load'
load 'libs/bats-assert/load'
# https://github.com/bats-core/bats-file#Index-of-all-functions
load 'libs/bats-file/load'
# https://github.com/bats-core/bats-assert#usage
load 'assert_utils'

source src/the_bash_script.sh


@test "Check if ssh-account is activated after activating it." {
    activate_ssh_account "some_git_username"
    assert_equal "Something" "Something_else"
}

It hangs indefinitely.它无限期地挂起。

Question问题

How can I activate an ssh-account without causing the BATS tests to hang indefinitely?如何在不导致 BATS 测试无限期挂起的情况下激活 ssh 帐户?

The test hangs indefinitely because BATS waits for ssh-agent to terminate (which runs in the background once line eval "$(ssh-agent -s)" is executed).测试无限期挂起,因为 BATS 等待ssh-agent终止(一旦执行eval "$(ssh-agent -s)"行,它将在后台运行)。 To be more specific, BATS waits for file descriptor 3 to be closed (which is being held open by ssh-agent ).更具体地说,BATS 等待文件描述符 3关闭(由ssh-agent保持打开状态)。

Thus, this can be solved by either implementing the workaround mentioned in the documentation or by killing ssh-agent .因此,这可以通过实施文档中提到的解决方法或杀死ssh-agent来解决。


Workaround from documentation:文档中的解决方法:

#!/bin/bash
# Activates/enables the ssh for 
activate_ssh_account() {
    git_username=$1
    eval "$(ssh-agent -s 3>&-)"
    ssh-add ~/.ssh/"$git_username"
}

This closes fd 3 for ssh-agent and BATS will no longer hang.这将关闭ssh-agent fd 3,并且 BATS 将不再挂起。 Note that this leaves ssh-agent running in the background, even after BATS exits.请注意,这会使ssh-agent在后台运行,即使在 BATS 退出后也是如此。 It is unclear from your question if that is desired or not.从您的问题中不清楚是否需要这样做。 If it's not, use the alternative below.如果不是,请使用下面的替代方法。


Kill ssh-agent :杀死ssh-agent

Add a cleanup trap to activate_ssh_account :activate_ssh_account添加清理陷阱:

#!/bin/bash
# Activates/enables the ssh for 
activate_ssh_account() {
    trap "trap - RETURN; kill \$SSH_AGENT_PID" RETURN
    git_username=$1
    eval "$(ssh-agent -s)"
    ssh-add ~/.ssh/"$git_username"
}

The trap is executed when the function exits and kills ssh-agent using the pid exported by eval "$(ssh-agent -s)" (ie variable SSH_AGENT_PID ).当 function 退出并使用eval "$(ssh-agent -s)"导出的 pid(即变量SSH_AGENT_PID )杀死ssh-agent时,将执行陷阱。

If you don't want to use a trap for some reason, this will also work:如果您出于某种原因不想使用陷阱,这也可以:

#!/bin/bash
# Activates/enables the ssh for
activate_ssh_account() {
    git_username=$1
    eval "$(ssh-agent -s)"
    result=0
    ssh-add ~/.ssh/"$git_username" || result=$?
    kill $SSH_AGENT_PID
    return $result
}

Note that the ||注意|| construct is necessary because BATS will stop executing the function's code once a command fails (ie without || , kill will not be executed if ssh-add fails).构造是必要的,因为一旦命令失败,BATS 将停止执行函数的代码(即没有|| ,如果ssh-add失败,将不会执行kill )。


As a side note, to actually test if activate_ssh_account succeeds or fails, you should use assert_success instead of assert_equal (unless there is more code that you omitted in your question).作为旁注,要实际测试activate_ssh_account是成功还是失败,您应该使用assert_success而不是assert_equal (除非您在问题中省略了更多代码)。

I never used BATS but by reading the doc I can say that there is a specific command for sharing common code.我从未使用过 BATS,但通过阅读文档,我可以说有一个用于共享公共代码的特定命令。 You may need to specify the full path though:您可能需要指定完整路径:

load : Share common code load : 共享通用代码

You may want to share common code across multiple test files.您可能希望跨多个测试文件共享通用代码。 Bats includes a convenient load command for sourcing a Bash source file relative to the location of the current test file. Bats 包含一个方便的加载命令,用于获取相对于当前测试文件位置的 Bash 源文件。 For example, if you have a Bats test in test/foo.bats , the command例如,如果您在test/foo.bats中有一个 Bats 测试,则该命令

load test_helper

will source the script test/test_helper.bash in your test file.将在您的测试文件中获取脚本 test/test_helper.bash。 This can be useful for sharing functions to set up your environment or load fixtures.这对于共享功能以设置您的环境或加载固定装置很有用。

Option1:选项1:

Try replacing尝试更换

source src/the_bash_script.sh

with

load '/full/path/to/src/the_bash_script.sh'
Option 2:选项 2:

Try adding the sourcing in @test尝试在@test中添加采购

@test "Check if ssh-account is activated after activating it." {
    source /full/path/to/src/the_bash_script.sh
    activate_ssh_account "some_git_username"
    assert_equal "Something" "Something_else"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM