各种问题杂项

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技巧

  1. git show HEAD 显示提交的具体代码
  2. 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:可以自己写一份代码再验证一下上述的说法,说的再多不如实际操作一波,这个问题,的确让自己明白了理解内存分配的重要意义。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值