【问题标题】: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 脚本运行得更早,并且可以假设对硬件的完全和独占访问。)

标签: bash shell sh


【解决方案1】:

虽然它可能不是一个有用的功能,但 OP 会发现在 python 脚本中执行起来更简单(bash 的功能更有限)。

这两种情况的最大缺点是脚本可以进行检查的时间间隔非常小 - 按键可能会被其他进程占用。

如果只有一个进程,那么可以使用 bash read 命令,例如 Bash script listen for key press to move on

但是,如果脚本错过了初始按键,则感觉键盘状态似乎要困难得多:

【讨论】:

    【解决方案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您的回答。评论是短暂的,可以随时删除。
    猜你喜欢
    • 1970-01-01
    • 2015-06-27
    • 1970-01-01
    • 1970-01-01
    • 2015-10-14
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多