ssh连接远程主机执行脚本的环境变量问题

2023-10-27

近日在使用ssh命令ssh user@remote ~/myscript.sh登陆到远程机器remote上执行脚本时,遇到一个奇怪的问题:

~/myscript.sh: line n: app: command not found

app是一个新安装的程序,安装路径明明已通过/etc/profile配置文件加到环境变量中,但这里为何会找不到?如果直接登陆机器remote并执行~/myscript.sh时,app程序可以找到并顺利执行。但为什么使用了ssh远程执行同样的脚本就出错了呢?两种方式执行脚本到底有何不同?如果你也心存疑问,请跟随我一起来展开分析。
目录

    问题定位
    bash的四种模式
        interactive + login shell
            加载配置文件
            配置文件的意义
        non-interactive + login shell
        interactive + non-login shell
            加载配置文件
            bashrc VS profile
        non-interactive + non-login shell
            加载配置文件
        更为直观的示图
        典型模式总结
    再次尝试
    配置文件建议
    写在结尾

说明,本文所使用的机器是:SUSE Linux Enterprise。
问题定位

这看起来像是环境变量引起的问题,为了证实这一猜想,我在这条命令之前加了一句:which app,来查看app的安装路径。在remote本机上执行脚本时,它会打印出app正确的安装路径。但再次用ssh来执行时,却遇到下面的错误:

which: no app in (/usr/bin:/bin:/usr/sbin:/sbin)

这很奇怪,怎么括号中的环境变量没有了app程序的安装路径?不是已通过/etc/profile设置到PATH中了?再次在脚本中加入echo $PATH并以ssh执行,这才发现,环境变量仍是系统初始化时的结果:

/usr/bin:/bin:/usr/sbin:/sbin

这证明/etc/profile根本没有被调用。为什么?是ssh命令的问题么?

随后我又尝试了将上面的ssh分解成下面两步:

user@local > ssh user@remote    # 先远程登陆到remote上
user@remote> ~/myscript.sh      # 然后在返回的shell中执行脚本

结果竟然成功了。那么ssh以这两种方式执行的命令有何不同?带着这个问题去查询了man ssh:

    If command is specified, it is executed on the remote host instead of a login shell.

这说明在指定命令的情况下,命令会在远程主机上执行,返回结果后退出。而未指定时,ssh会直接返回一个登陆的shell。但到这里还是无法理解,直接在远程主机上执行和在返回的登陆shell中执行有什么区别?即使在远程主机上执行不也是通过shell来执行的么?难道是这两种方式使用的shell有什么不同?

暂时还没有头绪,但隐隐感到应该与shell有关。因为我通常使用的是bash,所以又去查询了man bash,才得到了答案。
bash的四种模式

在man page的INVOCATION一节讲述了bash的四种模式,bash会依据这四种模式而选择加载不同的配置文件,而且加载的顺序也有所不同。本文ssh问题的答案就存在于这几种模式当中,所以在我们揭开谜底之前先来分析这些模式。
interactive + login shell

第一种模式是交互式的登陆shell,这里面有两个概念需要解释:interactive和login:

login故名思义,即登陆,login shell是指用户以非图形化界面或者以ssh登陆到机器上时获得的第一个shell,简单些说就是需要输入用户名和密码的shell。因此通常不管以何种方式登陆机器后用户获得的第一个shell就是login shell。

interactive意为交互式,这也很好理解,interactive shell会有一个输入提示符,并且它的标准输入、输出和错误输出都会显示在控制台上。所以一般来说只要是需要用户交互的,即一个命令一个命令的输入的shell都是interactive shell。而如果无需用户交互,它便是non-interactive shell。通常来说如bash script.sh此类执行脚本的命令就会启动一个non-interactive shell,它不需要与用户进行交互,执行完后它便会退出创建的shell。

那么此模式最简单的两个例子为:

    用户直接登陆到机器获得的第一个shell
    用户使用ssh user@remote获得的shell

加载配置文件

这种模式下,shell首先加载/etc/profile,然后再尝试依次去加载下列三个配置文件之一,一旦找到其中一个便不再接着寻找:

    ~/.bash_profile
    ~/.bash_login
    ~/.profile

下面给出这个加载过程的伪代码:

execute /etc/profile
IF ~/.bash_profile exists THEN
    execute ~/.bash_profile
ELSE
    IF ~/.bash_login exist THEN
        execute ~/.bash_login
    ELSE
        IF ~/.profile exist THEN
            execute ~/.profile
        END IF
    END IF
END IF

为了验证这个过程,我们来做一些测试。首先设计每个配置文件的内容如下:

1 user@remote > cat /etc/profile
2 echo @ /etc/profile
3 user@remote > cat ~/.bash_profile
4 echo @ ~/.bash_profile
5 user@remote > cat ~/.bash_login
6 echo @ ~/.bash_login
7 user@remote > cat ~/.profile
8 echo @ ~/.profile

然后打开一个login shell,注意,为方便起见,这里使用bash -l命令,它会打开一个login shell,在man bash中可以看到此参数的解释:

    -l Make bash act as if it had been invoked as a login shell

进入这个新的login shell,便会得到以下输出:

@ /etc/profile
@ /home/user/.bash_profile

果然与文档一致,bash首先会加载全局的配置文件/etc/profile,然后去查找~/.bash_profile,因为其已经存在,所以剩下的两个文件不再会被查找。

接下来移除~/.bash_profile,启动login shell得到结果如下:

@ /etc/profile
@ /home/user/.bash_login

因为没有了~/.bash_profile的屏蔽,所以~/.bash_login被加载,但最后一个~/.profile仍被忽略。

再次移除~/.bash_login,启动login shell的输出结果为:

@ /etc/profile
@ /home/user/.profile

~/.profile终于熬出头,得见天日。通过以上三个实验,配置文件的加载过程得到了验证,除去/etc/profile首先被加载外,其余三个文件的加载顺序为:~/.bash_profile > ~/.bash_login > ~/.profile,只要找到一个便终止查找。

前面说过,使用ssh也会得到一个login shell,所以如果在另外一台机器上运行ssh user@remote时,也会得到上面一样的结论。
配置文件的意义

那么,为什么bash要弄得这么复杂?每个配置文件存在的意义是什么?

/etc/profile很好理解,它是一个全局的配置文件。后面三个位于用户主目录中的配置文件都针对用户个人,也许你会问为什么要有这么多,只用一个~/.profile不好么?究竟每个文件有什么意义呢?这是个好问题。

Cameron Newham和Bill Rosenblatt在他们的著作《Learning the bash Shell, 2nd Edition》的59页解释了原因:

    bash allows two synonyms for .bash_profile: .bash_login, derived from the C shell’s file named .login, and .profile, derived from the Bourne shell and Korn shell files named .profile. Only one of these three is read when you log in. If .bash_profile doesn’t exist in your home directory, then bash will look for .bash_login. If that doesn’t exist it will look for .profile.

    One advantage of bash’s ability to look for either synonym is that you can retain your .profile if you have been using the Bourne shell. If you need to add bash-specific commands, you can put them in .bash_profile followed by the command source .profile. When you log in, all the bash-specific commands will be executed and bash will source .profile, executing the remaining commands. If you decide to switch to using the Bourne shell you don’t have to modify your existing files. A similar approach was intended for .bash_login and the C shell .login, but due to differences in the basic syntax of the shells, this is not a good idea.

原来一切都是为了兼容,这么设计是为了更好的应付在不同shell之间切换的场景。因为bash完全兼容Bourne shell,所以.bash_profile和.profile可以很好的处理bash和Bourne shell之间的切换。但是由于C shell和bash之间的基本语法存在着差异,作者认为引入.bash_login并不是个好主意。所以由此我们可以得出这样的最佳实践:

    应该尽量杜绝使用.bash_login,如果已经创建,那么需要创建.bash_profile来屏蔽它被调用
    .bash_profile适合放置bash的专属命令,可以在其最后读取.profile,如此一来,便可以很好的在Bourne shell和bash之间切换了

non-interactive + login shell

第二种模式的shell为non-interactive login shell,即非交互式的登陆shell,这种是不太常见的情况。一种创建此shell的方法为:bash -l script.sh,前面提到过-l参数是将shell作为一个login shell启动,而执行脚本又使它为non-interactive shell。

对于这种类型的shell,配置文件的加载与第一种完全一样,在此不再赘述。
interactive + non-login shell

第三种模式为交互式的非登陆shell,这种模式最常见的情况为在一个已有shell中运行bash,此时会打开一个交互式的shell,而因为不再需要登陆,因此不是login shell。
加载配置文件

对于此种情况,启动shell时会去查找并加载/etc/bash.bashrc和~/.bashrc文件。

为了进行验证,与第一种模式一样,设计各配置文件内容如下:

1 user@remote > cat /etc/bash.bashrc
2 echo @ /etc/bash.bashrc
3 user@remote > cat ~/.bashrc
4 echo @ ~/.bashrc

然后我们启动一个交互式的非登陆shell,直接运行bash即可,可以得到以下结果:

@ /etc/bash.bashrc
@ /home/user/.bashrc

由此非常容易的验证了结论。
bashrc VS profile

从刚引入的两个配置文件的存放路径可以很容易的判断,第一个文件是全局性的,第二个文件属于当前用户。在前面的模式当中,已经出现了几种配置文件,多数是以profile命名的,那么为什么这里又增加两个文件呢?这样不会增加复杂度么?我们来看看此处的文件和前面模式中的文件的区别。

首先看第一种模式中的profile类型文件,它是某个用户唯一的用来设置全局环境变量的地方, 因为用户可以有多个shell比如bash, sh, zsh等, 但像环境变量这种其实只需要在统一的一个地方初始化就可以, 而这个地方就是profile,所以启动一个login shell会加载此文件,后面由此shell中启动的新shell进程如bash,sh,zsh等都可以由login shell中继承环境变量等配置。

接下来看bashrc,其后缀rc的意思为Run Commands,由名字可以推断出,此处存放bash需要运行的命令,但注意,这些命令一般只用于交互式的shell,通常在这里会设置交互所需要的所有信息,比如bash的补全、alias、颜色、提示符等等。

所以可以看出,引入多种配置文件完全是为了更好的管理配置,每个文件各司其职,只做好自己的事情。
non-interactive + non-login shell

最后一种模式为非交互非登陆的shell,创建这种shell典型有两种方式:

    bash script.sh
    ssh user@remote command

这两种都是创建一个shell,执行完脚本之后便退出,不再需要与用户交互。
加载配置文件

对于这种模式而言,它会去寻找环境变量BASH_ENV,将变量的值作为文件名进行查找,如果找到便加载它。

同样,我们对其进行验证。首先,测试该环境变量未定义时配置文件的加载情况,这里需要一个测试脚本:

1 user@remote > cat ~/script.sh
2 echo Hello World

然后运行bash script.sh,将得到以下结果:

Hello World

从输出结果可以得知,这个新启动的bash进程并没有加载前面提到的任何配置文件。接下来设置环境变量BASH_ENV:

1 user@remote > export BASH_ENV=~/.bashrc

再次执行bash script.sh,结果为:

@ /home/user/.bashrc
Hello World

果然,~/.bashrc被加载,而它是由环境变量BASH_ENV设定的。
更为直观的示图

至此,四种模式下配置文件如何加载已经讲完,因为涉及的配置文件有些多,我们再以两个图来更为直观的进行描述:

第一张图来自这篇文章,bash的每种模式会读取其所在列的内容,首先执行A,然后是B,C。而B1,B2和B3表示只会执行第一个存在的文件:

+----------------+--------+-----------+---------------+
|                | login  |interactive|non-interactive|
|                |        |non-login  |non-login      |
+----------------+--------+-----------+---------------+
|/etc/profile    |   A    |           |               |
+----------------+--------+-----------+---------------+
|/etc/bash.bashrc|        |    A      |               |
+----------------+--------+-----------+---------------+
|~/.bashrc       |        |    B      |               |
+----------------+--------+-----------+---------------+
|~/.bash_profile |   B1   |           |               |
+----------------+--------+-----------+---------------+
|~/.bash_login   |   B2   |           |               |
+----------------+--------+-----------+---------------+
|~/.profile      |   B3   |           |               |
+----------------+--------+-----------+---------------+
|BASH_ENV        |        |           |       A       |
+----------------+--------+-----------+---------------+

上图只给出了三种模式,原因是第一种login实际上已经包含了两种,因为这两种模式下对配置文件的加载是一致的。

另外一篇文章给出了一个更直观的图:

Bash加载文件顺序

上图的情况稍稍复杂一些,因为它使用了几个关于配置文件的参数:--login,--rcfile,--noprofile,--norc,这些参数的引入会使配置文件的加载稍稍发生改变,不过总体来说,不影响我们前面的讨论,相信这张图不会给你带来更多的疑惑。
典型模式总结

为了更好的理清这几种模式,下面我们对一些典型的启动方式各属于什么模式进行一个总结:

    登陆机器后的第一个shell:login + interactive
    新启动一个shell进程,如运行bash:non-login + interactive
    执行脚本,如bash script.sh:non-login + non-interactive
    运行头部有如#!/usr/bin/env bash的可执行文件,如./executable:non-login + non-interactive
    通过ssh登陆到远程主机:login + interactive
    远程执行脚本,如ssh user@remote script.sh:non-login + non-interactive
    远程执行脚本,同时请求控制台,如ssh user@remote -t 'echo $PWD':non-login + interactive
    在图形化界面中打开terminal:
    Linux上: non-login + interactive
    Mac OS X上: login + interactive

相信你在理解了login和interactive的含义之后,应该会很容易对上面的启动方式进行归类。
再次尝试

在介绍完bash的这些模式之后,我们再回头来看文章开头的问题。ssh user@remote ~/myscript.sh属于哪一种模式?相信此时你可以非常轻松的回答出来:non-login + non-interactive。对于这种模式,bash会选择加载$BASH_ENV的值所对应的文件,所以为了让它加载/etc/profile,可以设定:

1 user@local > export BASH_ENV=/etc/profile

然后执行上面的命令,但是很遗憾,发现错误依旧存在。这是怎么回事?别着急,这并不是我们前面的介绍出错了。仔细查看之后才发现脚本myscript.sh的第一行为#!/usr/bin/env sh,注意看,它和前面提到的#!/usr/bin/env bash不一样,可能就是这里出了问题。我们先尝试把它改成#!/usr/bin/env bash,再次执行,错误果然消失了,这与我们前面的分析结果一致。

第一行的这个语句有什么用?设置成sh和bash有什么区别?带着这些疑问,再来查看man bash:

    If the program is a file beginning with #!, the remainder of the first line specifies an interpreter for the program.

它表示这个文件的解释器,即用什么程序来打开此文件,就好比Windows上双击一个文件时会以什么程序打开一样。因为这里不是bash,而是sh,那么我们前面讨论的都不复有效了,真糟糕。我们来看看这个sh的路径:

1 user@remote > ll `which sh`
2 lrwxrwxrwx 1 root root 9 Apr 25  2014 /usr/bin/sh -> /bin/bash

原来sh只是bash的一个软链接,既然如此,BASH_ENV应该是有效的啊,为何此处无效?还是回到man bash,同样在INVOCATION一节的下部看到了这样的说明:

    If bash is invoked with the name sh, it tries to mimic the startup behavior of historical versions of sh as closely as possible, while conforming to the POSIX standard as well. When invoked as an interactive login shell, or a non-interactive shell with the –login option, it first attempts to read and execute commands from /etc/profile and ~/.profile, in that order. The –noprofile option may be used to inhibit this behavior. When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute. Since a shell invoked as sh does not attempt to read and execute commands from any other startup files, the –rcfile option has no effect. A non-interactive shell invoked with the name sh does not attempt to read any other startup files. When invoked as sh, bash enters posix mode after the startup files are read.

简而言之,当bash以是sh命启动时,即我们此处的情况,bash会尽可能的模仿sh,所以配置文件的加载变成了下面这样:

    interactive + login: 读取/etc/profile和~/.profile
    non-interactive + login: 同上
    interactive + non-login: 读取ENV环境变量对应的文件
    non-interactive + non-login: 不读取任何文件

这样便可以解释为什么出错了,因为这里属于non-interactive + non-login,所以bash不会读取任何文件,故而即使设置了BASH_ENV也不会起作用。所以为了解决问题,只需要把sh换成bash,再设置环境变量BASH_ENV即可。

另外,其实我们还可以设置参数到第一行的解释器中,如#!/bin/bash --login,如此一来,bash便会强制为login shell,所以/etc/profile也会被加载。相比上面那种方法,这种更为简单。
配置文件建议

回顾一下前面提到的所有配置文件,总共有以下几种:

    /etc/profile
    ~/.bash_profile
    ~/.bash_login
    ~/.profile
    /etc/bash.bashrc
    ~/.bashrc
    $BASH_ENV
    $ENV

不知你是否会有疑问,这么多的配置文件,究竟每个文件里面应该包含哪些配置,比如PATH应该在哪?提示符应该在哪配置?启动的程序应该在哪?等等。所以在文章的最后,我搜罗了一些最佳实践供各位参考。(这里只讨论属于用户个人的配置文件)

    ~/.bash_profile:应该尽可能的简单,通常会在最后加载.profile和.bashrc(注意顺序)
    ~/.bash_login:在前面讨论过,别用它
    ~/.profile:此文件用于login shell,所有你想在整个用户会话期间都有效的内容都应该放置于此,比如启动进程,环境变量等
    ~/.bashrc:只放置与bash有关的命令,所有与交互有关的命令都应该出现在此,比如bash的补全、alias、颜色、提示符等等。特别注意:别在这里输出任何内容(我们前面只是为了演示,别学我哈)

写在结尾

至此,我们详细的讨论完了bash的几种工作模式,并且给出了配置文件内容的建议。通过这些模式的介绍,本文开始遇到的问题也很容易的得到了解决。以前虽然一直使用bash,但真的不清楚里面包含了如此多的内容。同时感受到Linux的文档的确做得非常细致,在完全不需要其它安装包的情况下,你就可以得到一个非常完善的开发环境,这也曾是Eric S. Raymond在其著作《UNIX编程艺术》中提到的:UNIX天生是一个非常完善的开发机器。本文几乎所有的内容你都可以通过阅读man page得到。最后,希望在这样一个被妖魔化的特殊日子里,这篇文章能够为你带去一丝帮助。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ssh连接远程主机执行脚本的环境变量问题 的相关文章

  • 从 PHP 启动交互式 SSH bash 会话

    我正在使用 PHP 编写常见服务器管理任务的快捷方式 我正在使用deployer org 但这应该不重要 我想添加一个任务 用于在通过 SSH 连接到服务器后启动交互式 bash 提示符 例如 您将运行 dep ssh 其中 dep 是一个
  • 如何在 Python 中将列表变量传递给 subprocess.call 命令

    我有一个清单 apps apps append wq35a5huqlja45jsyukrpmwuiayovrmh apps append q7mimvgduueernwvw4y22t5huemykntw apps append pmudbp
  • 在 Bourne Shell 中从变量中删除换行符

    在 bourne shell 中我有以下内容 VALUES some command that returns multiple line values echo VALUES 好像 ONE TWO THREE FOUR 我希望它看起来像
  • 使用 sed 和 pstree 显示正在使用的终端类型

    我一直在尝试仅显示用作名称的终端类型 例如 如果我使用 konsole 它会显示 konsole 到目前为止我一直在使用这个命令 pstree A s 输出这个 systemd konsole bash pstree 我有以下内容可以从该行
  • If 语句不遵循其条件

    在我的滚动代码中 您只需编写 r 然后按 Enter 键 但似乎不会读取该内容并转到重新启动 while 循环的 else 让它滚动的唯一方法是输入除 r 之外的其他内容 而不是 standard in 1 解析错误 bin bash th
  • Shell 脚本 - 迭代空格分隔的单词/字符(在 zsh 中)

    我在弄清楚如何在 shell 脚本中迭代空格分隔的单词 字符时遇到一些麻烦 例如 我想迭代一个包含字母表中由空格分隔的字符的变量 注意 即使字母表变量包含空格分隔的字符串而不是字符 结果也应该是相同的 即 aa bb cc 而不是 a b
  • shell进程的并行执行

    有没有一个工具可以在 Windows 批处理文件中并行执行多个进程 我发现了一些有趣的 Linux 工具 parallel http mi eng cam ac uk er258 code parallel html and PPSS ht
  • 在大型文本文件中查找重复记录

    我在一台 Linux 机器 Redhat 上 并且有一个 11GB 的文本文件 文本文件中的每一行包含单个记录的数据 并且该行的前 n 个字符包含该记录的唯一标识符 该文件包含略多于 2700 万条记录 我需要验证文件中不存在具有相同唯一标
  • Bash 变量:区分大小写?

    Bash shell 脚本区分大小写吗 是可变的date与DATE 是的 它区分大小写 就像 UNIX 的其余部分一样 date and DATE是两个不同的变量 makefile and Makefile是两个不同的文件 h and H是
  • 打印一个字符串,并将其特殊字符打印为文字转义序列

    我在 shell bash 脚本中有一个字符串 我想打印字符串 并将其所有 特殊字符 例如换行符 制表符等 打印为文字转义序列 例如换行符打印为 n 选项卡打印为 t 等等 不确定我是否使用了正确的术语 该示例应该能够澄清问题 Exampl
  • 在 Linux 中使用仅限 CLI 的工具生成磁盘使用情况图/图表

    在这个问题中 https stackoverflow com questions 32230 tracking down where disk space has gone on linux有人询问如何在 Linux 中显示磁盘使用情况 我
  • 如何在 Laravel 中存储非 php 文件的模板?

    我们可以存储PHP模板文件使用bladeLaravel 中的模板引擎 但是 我想在远程服务器上创建一个配置文件 每个文件包含 20 30 行以上 到目前为止 我一直在使用Perl 我曾经执行 Perl 文件 该文件用于将内容转储到一个文件中
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • Bash 'printf' 相当于命令提示符?

    我希望在 Windows 命令提示符下将一些字符串输入通过管道传输到一个小型 C 程序 在 bash 中我可以使用 printf AAAAA x86 x08 x04 xed program 本质上 我需要一些东西来转义命令提示符中的那些十六
  • 如何获取与文件类型关联的图标路径和索引?

    给定一个文件类型 例如 txt 我怎样才能得到 path index 文件类型的关联图标路径和索引 例如 我想转换 txt into Path SystemRoot system32 imageres dll Index 102 有了这些信
  • subprocess.Popen args 参数的最大长度是多少?

    我在用Popen http docs python org library subprocess html using the subprocess modulesubprocess 模块中的函数来执行命令行工具 subprocess Po
  • 如何拆分一行并重新排列其元素?

    我在一行中有一些数据 如下所示 abc edf xyz rfg yeg udh 我想呈现如下数据 abc xyz yeg edf rfg udh 以便打印备用字段并用换行符分隔 有没有这样的衬里 下列awk脚本可以做到这一点 gt echo
  • 子 shell 何时继承其父 shell 环境?

    什么情况下将shell的环境传递给子shell 子 shell 始终从父 shell 获取所有变量 man bash将描述所有使用子shell的情况 主要是 command command command and command 所谓环境只
  • 通过 SSH 将变量传递给远程脚本

    我正在通过 SSH 从本地服务器在远程服务器上运行脚本 首先使用 SCP 复制该脚本 然后在传递一些参数时调用该脚本 如下所示 scp path to script server example org another path ssh s
  • 向伪 shell (pty) 发出命令

    我尝试使用 subprocess popen os spawn 来运行进程 但似乎需要伪终端 import pty master slave pty openpty os write master ls l 应该发送 ls l 到从属终端

随机推荐

  • 解决微信小程序报错request:fail url not in domain list

    问题 微信开发者工具能正常发送请求 在真机调试的时候发送请求报错 request fail url not in domain list 1 检查微信后台域名信息是否配置了request合法域名 2 检查微信本地设置 将不校验合法域名勾选上
  • 运动目标检测--光流法

    一 概述 运动目标检测是指当监控场景中有活动目标时 采用图像分割的方法从背景图像中提取出目标的运动区域 运动目标检测技术是智能视频分析的基础 因为目标跟踪 行为理解等视频分析算法都是针对目标区域的像素点进行的 目标检测的结果直接决定着智能视
  • maven私服搭建

    文章目录 前言 一 Nexus 二 安装nexus 2 1在Mac终端输入 如果提示没有brew命令 请先安装brew 2 2启动nexus 2 3访问web管理系统 三 nexus的配置 3 1登录后开始设置操作 3 1 1设置新密码 3
  • 笔记/Linux运维面试常见问题

    linux基础 linux的特点 免费 开源 单根目录树 多用户多任务 区分大小写 一切皆文件 不以扩展名区分文件类型 Linux的必须分区有哪些 根分区 swap分区 swap分区的作用 物理内存不足时 未使用的进程可以临时保存到swap
  • 浅谈EL表达式

    目录 EL表达式 什么是EL表达式 EL表达式的语法 EL表达式中的查找并输出 EL运算符 EL算数运算符 EL比较运算符 EL逻辑运算符 EL其他运算符 EL表达式 什么是EL表达式 EL 提供了更为简洁 方便的形式来访问变量和参数 不仅
  • 黑盒测试-等价类划分法与边界值分析法-三角形问题

    等价类划分法 等价类划分可以把全部输人数据合理划分为若干等价类 在每一个等价类中取个数据作为测试的输人条件 就可以用少量代表性的测试数据取得较好的测试效果 有效等价类 指对于程序规格说明来说 由合理的 有意义的输入数据构成的集合 利用它 可
  • 对于傅里叶变换的小结

    原本写在word中 含有一些公式不容易搬移 因此输出长图发布在博客中 个人理解有限 如有错误欢迎交流指出 关于参数化谱估计可以参考我以前的几篇博客 Yule Walker方程法参数化谱估计 Python实现版 Levinson Durbin
  • Ceres与colmap安装

    已在ubuntu18 04上成功安装ceres1 14 0和colmap ceres1 14 0基本没错 找tag里的1 14 0压缩包 因为复制的git链接都指定了下载最新版本 colmap 安装cmakelist 添加set CMAKE
  • 深入了解C/C++开发就业前景如何?

    C C 编程语言 作为编程行业里出现较早的编程语言 几十年来 因为语言灵活 数据结构丰富 具有结构化 平台移植力强 程序执行效率高等特点 广受关注与应用 深入了解C C 开发就业前景如何 即使新编程语言不断涌出 智能化水平越来越高 也无法挑
  • 牧师与恶魔过河游戏——智能提示

    前言 这次实现一个含提示功能的牧师与恶魔过河小游戏 主要在上一个版本的牧师与恶魔小游戏上进行更改 通过增加一个状态计算和改版了得寻路算法 实现向玩家提示如何胜利完成游戏 游戏主体实现思路见上一篇博客 牧师与恶魔小游戏 动作分离版 游戏效果图
  • 考研英语二大作文模板/图表作文,英语图表作文这一篇就够了

    常见图表类型 表格 它表示多种事物的相互关系 曲线 它常表示事物的变化趋势 柱状 它用来表示几种事物的变化情况及相互关系 饼状 表示各事物在总体中所占的比例及相互关系 其中 柱形图和饼形图出现的频率比较高 图表作文结构 Para 1 描述图
  • 电动车结构及其工作原理

    电动车结构及其工作原理 文章目录 电动车结构及其工作原理 电动车定义 电动车结构 电源系统 电力驱动系统 整车控制器 辅助系统 电动车可能存在的结构形式 电动车定义 纯电动汽车是完全由可充电电池 如铅酸电池 镍镉电池 镍氢电池或锂电子电池
  • Ubuntu更改下载源

    Ubuntu更改下载源 今天美滋滋的打开ubuntu准备下载一个语言包 对于英语不好的我来说 看全英文版的ubuntu系统太吃力了 感觉系统极其不友好 哈哈 然后准备下在一个语言包 但是下载速度及其的慢 只有十几kb每秒 如果按照这样的速度
  • FastAPI利用装饰器实现定时任务

    因为 FastAPI 本身就是高性能异步框架 所以在不使用任何第三方定时任务模块的情况下 FastAPI 也可以很方便的实现定时任务 创建一个 tasks py 文件 复制下面的装饰器代码 import asyncio from logur
  • MyBatis详细执行流程

    目录 MyBatis详细的执行流程 1 创建加载核心配置文件的inputStream流 1 1 Recourse getResourceAsStream String resource 方法 1 2 getResourceAsStream
  • React中使用CSS样式的五种方法,主流推荐CSS Modules和Styled Components

    前言 由于 React的JSX语法 能在React中使用样式的方式有很多 本文主要介绍在React中经常使用CSS样式的五种方法 1行内样式 2声明样式 3引入样式 4 CSS Modules模块化 5 Styled component 1
  • DolphinScheduler3.0.1(数据质量)

    DolphinScheduler3 0 1 数据质量 Refer 1 data quality jar包修改 1 配置文件修改 2 依赖不明确问题 3 scope多修改问题 2 实现方式 1 Spark提交 2 结构解析 1 图1 2 图2
  • Blender一些建模技巧与应用

    平滑卡线 加线 卡结构线 加线 时 按E均匀线条会使加线与边线均匀对齐 投影切割 投影切割 使用调形后的曲线 放到模型表面上方进行投影切割 投影形状是 曲线范围内所能看到的模型 就是切割后的形状 使用流程 1 调整好曲线与屏幕的角度 想完全
  • 并行计算之OpenMP简介

    OpenMP环境安装 基于ubuntu20 04 sudo apt get update sudo apt get install libomp dev OpenMP概述 面向多线程并行编码的编译指导语句 如 pragma omp para
  • ssh连接远程主机执行脚本的环境变量问题

    近日在使用ssh命令ssh user remote myscript sh登陆到远程机器remote上执行脚本时 遇到一个奇怪的问题 myscript sh line n app command not found app是一个新安装的程序