检查是不是在 bash 脚本中保留了 shift
Posted
技术标签:
【中文标题】检查是不是在 bash 脚本中保留了 shift【英文标题】:Check if shift is held in a bash script检查是否在 bash 脚本中保留了 shift 【发布时间】:2015-07-27 20:04:26 【问题描述】:在大多数 *nix 环境的引导过程中,许多命令会检查是否按住 shift 并更改其行为(引导至安全模式)。
我也想做同样的事情。我正在编写一个在启动时运行 python 脚本的脚本,但我希望能够按住 a 键以防止执行 python 脚本并将控制权返回给用户。
有人知道怎么做吗?
【问题讨论】:
我相信您将需要通过一些外部方法(sysctl 等)主动查询键盘状态。话虽如此,我认为这是一个可怕的想法。它本质上是活泼和不可靠的。如果您确实需要可以在启动时而不是提前设置的东西,那么启动标志将是一个更好的选择。 请注意,您的 Python 脚本不会有相同的资源可用于固件或引导加载程序(它们比您的 Python 脚本运行得更早,并且可以假设对硬件的完全和独占访问。) 【参考方案1】:虽然它可能不是一个有用的功能,但 OP 会发现在 python 脚本中执行起来更简单(bash 的功能更有限)。
这两种情况的最大缺点是脚本可以进行检查的时间间隔非常小 - 按键可能会被其他进程占用。
如果只有一个进程,那么可以使用 bash read
命令,例如 Bash script listen for key press to move on
但是,如果脚本错过了初始按键,则感觉键盘状态似乎要困难得多:
Is it possible for a daemon (i.e. background) process to look for key-presses from a USB keyboard? 中的冗长示例似乎适用于 events(过去的)而不是 states。 How to get keyboard state in Linux? 中也提到了这一点 另见Accessing Keys from Linux Input Device【讨论】:
【参考方案2】:你可以试试这个 c++ 代码。
要编译它,你可以使用g++ -std=c++17 -w -O3 main.cpp -o readkey
。
使用ioctl(fileno(fpKbd.get()), EVIOCGKEY(sizeof(keyMap)), keyMap);
的代码使用EVIOCGKEY
轮询Linux 键盘上的所有键状态。然后检查并打印所有按下的键。
这是另一个例子:https://newbedev.com/how-can-i-get-the-keyboard-state-in-linux
#include <string.h>
#include <memory>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <linux/input.h>
std::string GetKey(char ch)
switch (ch)
case KEY_ESC:
return "KEY_ESC";
case KEY_1:
return "KEY_1";
case KEY_2:
return "KEY_2";
case KEY_3:
return "KEY_3";
case KEY_4:
return "KEY_4";
case KEY_5:
return "KEY_5";
case KEY_6:
return "KEY_6";
case KEY_7:
return "KEY_7";
case KEY_8:
return "KEY_8";
case KEY_9:
return "KEY_9";
case KEY_0:
return "KEY_0";
case KEY_MINUS:
return "KEY_MINUS";
case KEY_EQUAL:
return "KEY_EQUAL";
case KEY_BACKSPACE:
return "KEY_BACKSPACE";
case KEY_TAB:
return "KEY_TAB";
case KEY_Q:
return "KEY_Q";
case KEY_W:
return "KEY_W";
case KEY_E:
return "KEY_E";
case KEY_R:
return "KEY_R";
case KEY_T:
return "KEY_T";
case KEY_Y:
return "KEY_Y";
case KEY_U:
return "KEY_U";
case KEY_I:
return "KEY_I";
case KEY_O:
return "KEY_O";
case KEY_P:
return "KEY_P";
case KEY_LEFTBRACE:
return "KEY_LEFTBRACE";
case KEY_RIGHTBRACE:
return "KEY_RIGHTBRACE";
case KEY_ENTER:
return "KEY_ENTER";
case KEY_LEFTCTRL:
return "KEY_LEFTCTRL";
case KEY_A:
return "KEY_A";
case KEY_S:
return "KEY_S";
case KEY_D:
return "KEY_D";
case KEY_F:
return "KEY_F";
case KEY_G:
return "KEY_G";
case KEY_H:
return "KEY_H";
case KEY_J:
return "KEY_J";
case KEY_K:
return "KEY_K";
case KEY_L:
return "KEY_L";
case KEY_SEMICOLON:
return "KEY_SEMICOLON";
case KEY_APOSTROPHE:
return "KEY_APOSTROPHE";
case KEY_GRAVE:
return "KEY_GRAVE";
case KEY_LEFTSHIFT:
return "KEY_LEFTSHIFT";
case KEY_BACKSLASH:
return "KEY_BACKSLASH";
case KEY_Z:
return "KEY_Z";
case KEY_X:
return "KEY_X";
case KEY_C:
return "KEY_C";
case KEY_V:
return "KEY_V";
case KEY_B:
return "KEY_B";
case KEY_N:
return "KEY_N";
case KEY_M:
return "KEY_M";
case KEY_COMMA:
return "KEY_COMMA";
case KEY_DOT:
return "KEY_DOT";
case KEY_SLASH:
return "KEY_SLASH";
case KEY_RIGHTSHIFT:
return "KEY_RIGHTSHIFT";
case KEY_KPASTERISK:
return "KEY_KPASTERISK";
case KEY_LEFTALT:
return "KEY_LEFTALT";
case KEY_SPACE:
return "KEY_SPACE";
case KEY_CAPSLOCK:
return "KEY_CAPSLOCK";
case KEY_F1:
return "KEY_F1";
case KEY_F2:
return "KEY_F2";
case KEY_F3:
return "KEY_F3";
case KEY_F4:
return "KEY_F4";
case KEY_F5:
return "KEY_F5";
case KEY_F6:
return "KEY_F6";
case KEY_F7:
return "KEY_F7";
case KEY_F8:
return "KEY_F8";
case KEY_F9:
return "KEY_F9";
case KEY_F10:
return "KEY_F10";
case KEY_NUMLOCK:
return "KEY_NUMLOCK";
case KEY_SCROLLLOCK:
return "KEY_SCROLLLOCK";
case KEY_KP7:
return "KEY_KP7";
case KEY_KP8:
return "KEY_KP8";
case KEY_KP9:
return "KEY_KP9";
case KEY_KPMINUS:
return "KEY_KPMINUS";
case KEY_KP4:
return "KEY_KP4";
case KEY_KP5:
return "KEY_KP5";
case KEY_KP6:
return "KEY_KP6";
case KEY_KPPLUS:
return "KEY_KPPLUS";
case KEY_KP1:
return "KEY_KP1";
case KEY_KP2:
return "KEY_KP2";
case KEY_KP3:
return "KEY_KP3";
case KEY_KP0:
return "KEY_KP0";
case KEY_KPDOT:
return "KEY_KPDOT";
case KEY_ZENKAKUHANKAKU:
return "KEY_ZENKAKUHANKAKU";
case KEY_102ND:
return "KEY_102ND";
case KEY_F11:
return "KEY_F11";
case KEY_F12:
return "KEY_F12";
case KEY_RO:
return "KEY_RO";
case KEY_KATAKANA:
return "KEY_KATAKANA";
case KEY_HIRAGANA:
return "KEY_HIRAGANA";
case KEY_HENKAN:
return "KEY_HENKAN";
case KEY_KATAKANAHIRAGANA:
return "KEY_KATAKANAHIRAGANA";
case KEY_MUHENKAN:
return "KEY_MUHENKAN";
case KEY_KPJPCOMMA:
return "KEY_KPJPCOMMA";
case KEY_KPENTER:
return "KEY_KPENTER";
case KEY_RIGHTCTRL:
return "KEY_RIGHTCTRL";
case KEY_KPSLASH:
return "KEY_KPSLASH";
case KEY_SYSRQ:
return "KEY_SYSRQ";
case KEY_RIGHTALT:
return "KEY_RIGHTALT";
case KEY_HOME:
return "KEY_HOME";
case KEY_UP:
return "KEY_UP";
case KEY_PAGEUP:
return "KEY_PAGEUP";
case KEY_LEFT:
return "KEY_LEFT";
case KEY_RIGHT:
return "KEY_RIGHT";
case KEY_END:
return "KEY_END";
case KEY_DOWN:
return "KEY_DOWN";
case KEY_PAGEDOWN:
return "KEY_PAGEDOWN";
case KEY_INSERT:
return "KEY_INSERT";
case KEY_DELETE:
return "KEY_DELETE";
case KEY_MACRO:
return "KEY_MACRO";
case KEY_MUTE:
return "KEY_MUTE";
case KEY_VOLUMEDOWN:
return "KEY_VOLUMEDOWN";
case KEY_VOLUMEUP:
return "KEY_VOLUMEUP";
case KEY_POWER:
return "KEY_POWER";
case KEY_KPEQUAL:
return "KEY_KPEQUAL";
case KEY_KPPLUSMINUS:
return "KEY_KPPLUSMINUS";
case KEY_PAUSE:
return "KEY_PAUSE";
case KEY_KPCOMMA:
return "KEY_KPCOMMA";
case KEY_HANGUEL:
return "KEY_HANGUEL";
case KEY_HANJA:
return "KEY_HANJA";
case KEY_YEN:
return "KEY_YEN";
case KEY_LEFTMETA:
return "KEY_LEFTMETA";
case KEY_RIGHTMETA:
return "KEY_RIGHTMETA";
case KEY_COMPOSE:
return "KEY_COMPOSE";
case KEY_STOP:
return "KEY_STOP";
case KEY_CALC:
return "KEY_CALC";
case KEY_SETUP:
return "KEY_SETUP";
case KEY_SLEEP:
return "KEY_SLEEP";
case KEY_WAKEUP:
return "KEY_WAKEUP";
case KEY_PROG1:
return "KEY_PROG1";
case KEY_SCREENLOCK:
return "KEY_SCREENLOCK";
case KEY_MAIL:
return "KEY_MAIL";
case KEY_BOOKMARKS:
return "KEY_BOOKMARKS";
case KEY_COMPUTER:
return "KEY_COMPUTER";
case KEY_BACK:
return "KEY_BACK";
case KEY_FORWARD:
return "KEY_FORWARD";
case KEY_EJECTCLOSECD:
return "KEY_EJECTCLOSECD";
case KEY_NEXTSONG:
return "KEY_NEXTSONG";
case KEY_PLAYPAUSE:
return "KEY_PLAYPAUSE";
case KEY_PREVIOUSSONG:
return "KEY_PREVIOUSSONG";
case KEY_STOPCD:
return "KEY_STOPCD";
case KEY_HOMEPAGE:
return "KEY_HOMEPAGE";
case KEY_REFRESH:
return "KEY_REFRESH";
case KEY_F13:
return "KEY_F13";
case KEY_F14:
return "KEY_F14";
case KEY_F15:
return "KEY_F15";
case KEY_F21:
return "KEY_F21";
case KEY_SUSPEND:
return "KEY_SUSPEND";
case KEY_CAMERA:
return "KEY_CAMERA";
case KEY_EMAIL:
return "KEY_EMAIL";
case KEY_SEARCH:
return "KEY_SEARCH";
case KEY_BRIGHTNESSDOWN:
return "KEY_BRIGHTNESSDOWN";
case KEY_BRIGHTNESSUP:
return "KEY_BRIGHTNESSUP";
case KEY_MEDIA:
return "KEY_MEDIA";
case KEY_SWITCHVIDEOMODE:
return "KEY_SWITCHVIDEOMODE";
case KEY_BATTERY:
return "KEY_BATTERY";
case KEY_UNKNOWN:
return "KEY_UNKNOWN";
return "UNKNOWN";
std::vector<std::string> GetKeyboard()
std::ifstream file("/proc/bus/input/devices");
if (!file.is_open())
std::cout << "unable to open devices" << std::endl;
return ;
std::vector<std::string> keyboards;
bool inKeyboardSection = false;
for (std::string line; getline(file, line);)
std::transform(line.begin(), line.end(), line.begin(), ::tolower);
if (line.find("keyboard") != line.npos)
inKeyboardSection = true;
if (inKeyboardSection && line.empty())
inKeyboardSection = false;
if (inKeyboardSection && line.find("h: handlers=") != line.npos && line.find("kbd") != line.npos)
auto start = line.find("event");
auto end = line.find(" ", start);
if (start != line.npos && end != line.npos)
keyboards.push_back("/dev/input/" + line.substr(start, end - start));
return keyboards;
int main(int argc, char* argv[])
auto kbds = GetKeyboard();
if (kbds.empty())
std::cout << "no keyboard found" << std::endl;
return 1;
std::string keys;
for (auto kbd : kbds)
auto deleter = [](FILE* fd) fclose(fd); ;
std::unique_ptr<FILE, decltype(deleter)> fpKbd(fopen(kbd.c_str(), "r"), deleter);
if (!fpKbd)
std::cout << "unable to open keyboard" << std::endl;
return 1;
char keyMap[KEY_MAX / 8 + 1];
memset(keyMap, 0, sizeof(keyMap));
ioctl(fileno(fpKbd.get()), EVIOCGKEY(sizeof(keyMap)), keyMap);
for (int i = 0; i < KEY_MAX / 8 + 1; ++i)
auto ch = keyMap[i];
for (int j = 0; j < 8; ++j)
if ((ch >> j) & 1)
if (!keys.empty())
keys += ",";
keys += GetKey(i * 8 + j);
if (!keys.empty())
std::cout << keys << std::endl;
【讨论】:
这是大量的代码,只是为了检查 shift 键是否被按下。你在哪里得到它?你应该引用你的来源。请把它精简到相关的部分。 你能解释一下它是如何工作的吗?没有解释的代码转储不是很有用。 代码使用ioctl(fileno(fpKbd.get()), EVIOCGKEY(sizeof(keyMap)), keyMap);
使用EVIOCGKEY 轮询Linux 键盘上的所有键状态。然后检查并打印所有按下的键。
请edit您的回答。评论是短暂的,可以随时删除。以上是关于检查是不是在 bash 脚本中保留了 shift的主要内容,如果未能解决你的问题,请参考以下文章