这与hash命令的目的是什么?安装程序后,我正在寻找一种方法来告诉所有打开的 shell 更新其缓存。我经常打开 6 到 8 个,但我不想运行hash -r
8 或 10 次。任何事情超过一次都是浪费时间和精力。
在一个 shell 中安装程序后,是否可以 (1) 让所有 shell 重建其缓存程序的视图;或者 (2) 重建表并将该表用于所有其他 shell?如果可以的话,我们该怎么做呢?
这是 的相关部分man 1 hash
,但没有讨论如何在全球范围内取得成果。
hash [-lr] [-p filename] [-dt] [name]
Each time hash is invoked, the full pathname of the command name
is determined by searching the directories in $PATH and remem‐
bered. Any previously-remembered pathname is discarded. If the
-p option is supplied, no path search is performed, and filename
is used as the full filename of the command. The -r option
causes the shell to forget all remembered locations. The -d
option causes the shell to forget the remembered location of
each name. If the -t option is supplied, the full pathname to
which each name corresponds is printed. If multiple name argu‐
ments are supplied with -t, the name is printed before the
hashed full pathname. The -l option causes output to be dis‐
played in a format that may be reused as input. If no arguments
are given, or if only -l is supplied, information about remem‐
bered commands is printed. The return status is true unless a
name is not found or an invalid option is supplied.
答案1
这是 TLDR 解决方案:如果您想以编程方式在预先存在的 shell 会话中执行命令,那么您可以使用该ttyecho
程序。
警告: 请注意,这通常不是一个安全的操作,并且对每个会话的状态很敏感。正如用户 StephenKitt 指出的那样,这种方法要求每个终端会话都有一个等待接收输入的提示。
PROMPT_COMMAND='hash -r'
另一种解决方案是通过将语句添加到文件中来有效禁用路径散列~/.bashrc
。这不会影响当前正在运行的会话,但会防止将来出现此问题。
最后,您可以考虑使用终端多路复用器,例如多路复用器,支持在多个终端同时执行命令。
以下是更详细的回应。
在我看来,您正在寻找的基本功能是能够在其他活动 shell 会话中以编程方式执行命令。我发现这个问题(如何在其他 shell 会话中执行命令)已在本网站的其他地方得到解决,例如:
在其他活动 shell 会话中执行命令的最简单方法似乎是使用该ttyecho
实用程序。该ttyecho
程序是一个小型、独立的单文件 C 程序。以下是ttyecho
源代码和文档的一些参考:
为了完整起见,这里是源代码:
// ttyecho.c
// Original author: Pratik Sinha
// http://www.humbug.in/2010/utility-to-send-commands-or-data-to-other-terminals-ttypts/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <string.h>
#include <unistd.h>
void print_help(char *prog_name) {
printf("Usage: %s [-n] DEVNAME COMMAND\n", prog_name);
printf("Usage: '-n' is an optional argument if you want to push a new line at the end of the text\n");
printf("Usage: Will require 'sudo' to run if the executable is not setuid root\n");
exit(1);
}
int main (int argc, char *argv[]) {
char *cmd, *nl = "\n";
int i, fd;
int devno, commandno, newline;
int mem_len;
devno = 1; commandno = 2; newline = 0;
if (argc < 3) {
print_help(argv[0]);
}
if (argc > 3 && argv[1][0] == '-' && argv[1][1] == 'n') {
devno = 2; commandno = 3; newline=1;
} else if (argc > 3 && argv[1][0] == '-' && argv[1][1] != 'n') {
printf("Invalid Option\n");
print_help(argv[0]);
}
fd = open(argv[devno],O_RDWR);
if(fd == -1) {
perror("open DEVICE");
exit(1);
}
mem_len = 0;
for ( i = commandno; i < argc; i++ ) {
mem_len += strlen(argv[i]) + 2;
if ( i > commandno ) {
cmd = (char *)realloc((void *)cmd, mem_len);
} else { //i == commandno
cmd = (char *)malloc(mem_len);
}
strcat(cmd, argv[i]);
// strcat(cmd, " ");
}
if (newline == 0)
usleep(225000);
for (i = 0; cmd[i]; i++)
ioctl (fd, TIOCSTI, cmd+i);
if (newline == 1)
ioctl (fd, TIOCSTI, nl);
close(fd);
free((void *)cmd);
exit (0);
}
如果您下载源代码或将其复制粘贴到名为 的文件中ttyecho.c
,那么您应该能够像这样编译程序:
gcc ttyecho.c -o ttyecho
程序编译完成后,您应该能够使用它在另一个 shell 会话中运行您想要的任何命令。这包括能够hash -r
在每个活动 shell 会话中以编程方式运行命令。以下是清除 Mac OS X 上所有 shell 会话上的散列命令的一种方法:
for _tty in /dev/ttys*; do ./ttyecho -n 'hash -r' ${_tty}; done
在 Linux 机器上,你可以这样做:
for _tty in /dev/pts/*; do ./ttyecho -n 'hash -r' ${_tty}; done
由于一些评论要求找到一种重现该问题的方法,因此我添加了以下脚本来说明哈希如何影响执行的程序。
# Create two bin directories
mkdir -p ~/local/bin1
mkdir -p ~/local/bin2
# Add the directories to the PATH, with bin2 preceding bin1
export PATH="${HOME}/local/bin2:${HOME}/local/bin1:${PATH}"
# Create a test script and put it in the bin1 directory
cat <<HEREDOC > ~/local/bin1/test.sh
#!/bin/bash
# test.sh
echo "This is test #1, it's in ~/local/bin1"
HEREDOC
# Make the script executable
chmod +x ~/local/bin1/test.sh
# Verify that the script is found by using the "which" command
which test.sh
# Output:
#
# /home/username/local/bin1/test.sh
# Verify that the script is found by using the "type" command
type test.sh
# Output:
#
# test.sh is /home/username/local/bin1/test.sh
# Test the script
test.sh
# Output:
#
# This is test #1, it's in ~/local/bin1
# Now hash the test script
hash test.sh
# Verify that the script has been hashed by using the "type" command
type test.sh
# Output:
#
# test.sh is hashed (/home/username/local/bin1/test.sh)
# Now create a second test script and put it in bin2 to shadow the first
cat <<HEREDOC > ~/local/bin2/test.sh
#!/bin/bash
# test.sh
echo "This is test #2, it's in ~/local/bin2"
HEREDOC
# Make the second test script executable
chmod +x ~/local/bin2/test.sh
# Verify that the bin2 test script take priority over the bin1 test script
which -a test.sh
# Output:
#
# /home/username/local/bin2/test.sh
# /home/username/local/bin1/test.sh
which test.sh
# Output:
#
# /home/username/local/bin2/test.sh
# Try to run the test script
test.sh
# Ouput:
#
# This is test #1, it's in ~/local/bin1
# NOTE: Even though bin2/test.sh comes before bin1/test.sh in the PATH,
# it's bin1/test.sh that is executed. What's going on?
# Use the "type" command to see which script is being executed
type test.sh
# Output
#
# test.sh is hashed (/home/username/local/bin1/test.sh)
# NOTE: That explains the seeming contradiction.
# Clear the hashed command
hash -d test.sh
# Check that the hashed command has been cleared
type test.sh
# Output:
#
# test.sh is /home/username/local/bin2/test.sh
# Run the test.sh command
test.sh
# Output:
#
# This is test #2, it's in ~/local/bin2
我还发现了本网站其他地方描述的替代方法:
解决方案是使用PROMPT_COMMAND
变量不断清除路径缓存,例如通过将以下行添加到您的~/.bashrc
:
PROMPT_COMMAND='hash -r'
请注意,这只会影响新会话,而不会影响您预先存在的会话,除非您也在这些会话中执行该命令。
最后,您可能需要考虑使用终端多路复用器,例如多路复用器。这是该网站的相关帖子: