检查是不是在 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(过去的)而不是 statesHow 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的主要内容,如果未能解决你的问题,请参考以下文章

Bash,...检查是不是安装了程序,使用 bash 脚本 [重复]

检查 Bash shell 脚本中是不是存在输入参数

如何检查是不是在 bash 脚本中以 root 身份运行

检查bash脚本中是不是存在mysql用户,出现错误

使用if else bash脚本检查变量是不是存在[重复]

检查bash中是不是存在程序