文章目录
Linux 杂项
- 通过sudo 执行某些操作时,可通过获取$SUDO_USER 的值,来获取执行sudo 命令的普通用户的用户名。
- linux 桌面系统命令行方式设置快捷键: dconf write /org/mate/desktop/keybindings/custom7/binding “‘key’”
- linux 下隐藏指定进程:
ps 命令会读取/proc目录下获取进程信息,从而才能在命令行中执行ps 去查看对应的进程信息。
利用 mount 中bind 参数将一个文件夹绑定在 进程id 对应的文件夹中,即可让ps 查看不到对应id 的进程信息。
sudo mount -o bind xx/ /proc/`pidof processname`` (反引号)
xx 代表的某文件夹。
此举可以暂时解决某些命令会带有用户名密码等信息,防止泄露
如,curl命令上传时,如果上传时间过长,可能会被其他人通过ps -ef |grep curl 查看到调用curl时传入的用户名和密码信息,导致信息泄露
FileZilla源码
- FileZilla中,对于拖拽的文件,如果带有中文路径或中文名,存在文件类型判断的bug(版本有点旧3.8.x,不知道新版本的时候是不是解决了)
在GetFileInfo前有尝试打印files[i],发现读取到的路径出现了问题。
只要路径中含有中文,结果会导致拖拽后的读到的路径会丢失几个字节(中文越多,丢失的越多),
猜测是wxWidgets 框架中的getdata函数中,在linux下对于含有中文的字符串长度的判断不好,从而导致,含有中文路径的数据,接收时丢失了部分尾端的数据,
结果就是导致了调用系统函数判断文件类型时,type 既不是file 也不是dir.(2020/09/01修改)
smb共享
- 清除在Windows下访问共享文件夹(smb共享)时的登录信息
BT速率解释
linux socket send导致的程序崩溃
- 当client 断开连接后,sever端往一个已经关闭的fd中send 数据,会导致触发SIGPIPE信号,该信号的默认行为是终止当前进程,因此会导致程序挂掉。
- 然而通常这种现象我们并不希望发生,可以有以下两种解决方式:
1、利用signal函数忽略SIGPIPE信号signal(SIGPIPE, SIG_IGN);
2、利用send函数最后一个flag参数,
send_len = send(client_fd, ptr, len, MSG_NOSIGNAL);
程序继续运行,于是我们也可以根据,send_len来判断异常,并且利用errno来获取具体的异常信息
send_len = send(client_fd, ptr, len, MSG_NOSIGNAL);
if(send_len < 0)
{
switch(errno)
{
case EPIPE:
{
do;
break;
}
case EINTR:
{
do;
break;
}
case EAGAIN:
{
do;
break;
}
default:
{
do;
break;
}
}
}
LINUX socket connect 奇怪的错误(eg:operation now in process)
如果是在connect 之前设置的非阻塞套接字,那么connect 没等连接成功就返回了,此时返回的错误码不一定是正确的,从而会导致出现奇奇怪怪的错误,误导问题定位
diff 与patch
这个功能在协作开发的时候使用比较方便,
diff -ru oldfile newfile > xxx.patch (r递归,u输出好看点)
patch -p1 < xxx.patch (p1 p0 啥的上网搜)
QT检测剪贴板内容变化
QClipboard *cb = QApplication::clipboard(); 可以获取到系统剪贴板
connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(deal()));
QClipboard 有自定义的信号,绑定一下对应的槽函数即可(不知道为啥网上关于qt剪贴板的资源好少,自己在qt帮助文档里看到的)
未整理的杂项
xdg-user-dir DESKTOP 查看桌面目录
xdg-user-dir 查看Home目录
xdg-open url 以系统默认浏览器打开指定url
xdg-mime query filetype /home/user/1.doc 查询指定文件的文件类型
xdg-mime default xx.desktop text/plain 指定文件类型设置默认打开方式
xdg-setting get default-web-browser 查询系统默认浏览器(目前验证麒麟可以,但是UOS 查询会出问题,可能跟UOS 的桌面环境相关)
以后需要执行什么操作,
可以着重去查找xdg下是否有这些操作
(是不是以前做的锁屏之类的命令也是?可拓展一下)
grep -E “pattern_1|pattern_2” 匹配多个字符串
grep -lZ | xargs -0 可以处理带有空格的文件名
列出当前所有的会话
loginctl list-sessions
锁定/解锁会话(如果会话支持屏幕锁)
如果指定了会话ID,那么将锁定/解锁指定会话,否则将锁定/解锁当前调用者的会话
loginctl lock-session [ID]
loginctl unlock-session [ID]
锁定/解锁所有支持屏幕锁的会话
loginctl lock-sessions
loginctl unlock-sessions
linux下 alternatives命令常用于同一个系统中安装同一软件的多个版本
/usr/share/applications 下放置xxx.desktop 可以让linux 所有用户在开始菜单栏中查看到应用
在/home/user/.local/share/applications 下放置xxx.desktop 只能让当前用户在开始菜单栏中查看到
mime匹配的desktop同理,
创建新的desktop文件到指定目录后,执行更新命令:(好像不执行也能识别)
update-desktop-database /usr/share/applications
快捷方式文件内容:
“[Desktop Entry]\n”
“Encoding=UTF-8\n”
“Name=%s\n”
“Exec=%s %d %s\n”
“Icon=%s/%s\n”
“StartupNotify=false\n”
“Type=Application\n”
“Categories=Application;\n”
“Company=sangfor\n”
“Name[zh_CN]=%s\n”
Name[zh_CN] 和Name字段同时存在时,以zh_CN显示的为准,并且对快捷方式进行重命名时,系统会修改zh_CN的值,但不影响Name的值
此外,目前麒麟上对快捷方式重命名会导致文件名跟随变化,UOS 文件名不受影响
mime匹配文件内容:
“[Desktop Entry]\n”
“Categories=Utility;TextEditor\n”
“Name=%s\n”
“Exec=%s %d %s %%F\n”
“Icon=%s/%s\n”
“MimeType=application/msword;application/pdf;”
“application/vnd.ms-powerpoint;”
“application/vnd.ms-excel;”
“application/vnd.openxmlformats-officedocument.wordprocessingml.document;\n”
“StartupNotify=false\n”
“Type=Application\n”
“author=lyg\n”
可以自己添加字段author=lyg, 并不报错,用来识别自己的文件
NoDisplay字段等于true 可以设置菜单不显示,但是右键可以选择
Hidden 字段等于true ,菜单也不显示,右键也不显示
xdg系列的工具:
RHEL 6 和 ubuntu 採用了 FreeDesktop.org 的規格,
官方網站 http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
定義了基本的 Linux 下的 X Window System (X11) 以及其他 Unix-like 作業系統的桌面環境.
主要是為了增加 free software desktop environments 的互通性,
而這環境簡稱為 XDG(X Desktop Group)
比如目前使用过的
xdg-user-dir 获取home目录
xdg-user-dir DESKTOP 获取桌面目录
xdg-open 使用默认程序打开指定的东西。比如使用默认的浏览器打开指定的网址 xdg-open https://127.0.0.1
关注并了解一下这两个宏,和system执行shell成功与否相关
(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)
两个比较好的system处理
// 使用此宏时,需定义 int sysRet; 用来保存返回值。
// 避免 定义 sys_status 变量,导致名字冲突。
#define SYSTEM(cmd)
do {
if ((cmd) == NULL)
{
LOGI("[SYSTEM] cmd is NULL");
}
int sys_status = system((cmd));
if (sys_status == -1)
{
LOGI("[SYSTEM] cmd(%s) status(-1)", (cmd));
sysRet = -1;
}
else if (!WIFEXITED(sys_status))
{
LOGI("[SYSTEM] cmd(%s) status(%d) WIFEXITED false", (cmd), sys_status);
sysRet = -1;
}
else if (WEXITSTATUS(sys_status) != 0)
{
LOGI("[SYSTEM] cmd(%s) status(%d) WEXITSTATUS false", (cmd), sys_status);
sysRet = WEXITSTATUS(sys_status);
}
else
{
sysRet = 0;
}
} while(0)
#endif
int do_system(const char *fmt, …)
{
char cmd[BUFSIZ] = “”;
va_list ap;
va_start(ap, fmt);
int num = vsnprintf(cmd, sizeof(cmd), fmt, ap);
va_end(ap);
if (num < 0 || num >= (int)sizeof(cmd))
return -1;
int ret = system(cmd);
if (ret < 0)
return -1;
return (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) ? 0 : -1;
}
qt 相关的经验总结:
1.信号处理:
signal(SIGTERM, handler);
void handler(int signum)
{
if(signum == SIGTERM)
{
qDebug()<<“sigterm”;
// st.close_action();
exit(0);
}
else if(signum == SIGUSR1)
{
qDebug("\nhwnd start######");
std::map<int, MainWindow*>::iterator iter = win_map.begin();
for(;iter != win_map.end(); ++iter)
{
qDebug()<first;
}
qDebug(“hwnd end######”);
}
}
2. 设置最后一个窗体关闭时,程序不退出
app.setQuitOnLastWindowClosed(false);
3.透明窗口鼠标穿透,使用xlib的东西
setAttribute(Qt::WA_TransparentForMouseEvents, true);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
XShapeCombineRectangles(QX11Info::display(), this->winId(), ShapeInput, 0, 0, NULL, 0, ShapeSet, YXBanded);
git技巧
- git show HEAD 显示提交的具体代码
- git commit --amend 修改上一次提交的内容,(已经提交未push,发现还有个东西没改就可以用这个)
比如在fun1.cpp的第45行设置断点:
break fun1.cpp:45
然后 p 变量名查看当前变量
GDB动态打印命令dprintf来实现print消息的输出,
dprintf原理
dprintf命令会设置一个特殊的断点,这可以通过info break查看,dprintf设置了类型为dprintf的特殊断点,当程序执行到该断点
时,GDB将按照template和expression打印消息,打印完成后继续执行程序。这个过程非常短暂(和仿真器的速度有关),人是感觉
不出程序停顿的,所以看起来就跟是目标程序在打印消息一样。
dprintf用法
在指定行打印
dprintf perf_msgr_client.cc:133,“Test send i = %d,ops = %d,inflight = %d\n”,i,ops,inflight
在指定函数打印
dprintf perf_msgr_client.cc:ready,“In fun ready:c= %d,jobs=%d\n”,c,jobs
gdb 遇到的一个异常退出的问题
参考链接
现象是:起spice 的时候,发现spice 异常退出了,但是很奇怪没有core 文件产生,于是用gdb attach看了一下,
发现gdb 报错:[Inferior 1 (process 27641) exited with code 0177]
查看当前堆栈,什么信息都没有?
就很奇怪,然后上网搜了,发现最后实际是因为动态库的原因,
很蠢, 建立了软连接 abc.1 -> abc.1.1.0 然后因为之前调试 将 abc1.1.0 改名为abc1.1.0_bak 然后copy了一个新的abc.1.1.0 我以为 软连接就会指向这个新的动态库。。。
遇到的一个有意思的题(内存分布问题)
class A
{
public:
int y = 5;
int x = 1;
void exec()
{
x = 2;
}
};
class B
{
public:
int x = 3;
int y = 6;
void exec()
{
x = 10;
}
};
A a;
B* bp = (B*)&a;
B b = *bp;
a.x = ? bp->x = ? b.x = ?
bp->exec();
a.x = ? bp->x = ? b.x = ?
ans is :
只能说自己对于C++ 的内存分配记忆还不是很深刻
第一行的a.x = 1 没问题,
bp->x 为什么等于5?
原因很简单,看一下内存里分布,A 类 前四个字节表示y,后四个字节才表示x,但是这时候强制类型转换了,bp指针是B 类的,而B类中前四个字节表示x,后四个字节才表示y,因此bp->x 打印A 类前四个字节,也就是5;
b.x 同样拷贝构造之后x=a.y=5;
执行了exec之后呢?
这里要明白一点,函数是存放在代码区的,类的所有对象共享这一份函数代码。
因此bp->exec 执行的是B类的函数,也就是将B 类中的x 变为10,实际上a类的x没有被修改值,因此,输出1 10 5
当然,此时a.y 已经被修改成10了
为了更进一步的了解:函数是存放在代码区的,再问一个问题:
如果一个类指针是空指针,让他执行成员函数会发生崩溃嘛?
ans:
可能会可能不会,
什么情况下会? 当你的成员函数需要操作成员变量的时候,空指针自然没有这些成员变量,这个操作就会导致段错误了。
(更新:操作虚函数应该也会崩溃)
什么情况不会?当你的成员函数不操作成员变量的时候,比如,就只做了打印输出,这种情况下是不会崩溃的
ps:可以自己写一份代码再验证一下上述的说法,说的再多不如实际操作一波,这个问题,的确让自己明白了理解内存分配的重要意义。