如果通过 cronjob 执行应用程序,Qt 输出(qDebug qWarning 等)不起作用
Qt output (qDebug qWarning etc) does not work if application is executed via cronjob
我为此创建了一个复制样本:
#include <iostream>
#include <QtCore/QLoggingCategory>
#include <QtCore/QDebug>
#include <QtCore/QtCore>
using namespace std;
int main () {
int i;
QLoggingCategory::setFilterRules("*.debug=true\n");
QLoggingCategory LogO(NULL);
if (LogO.isDebugEnabled()) {
cout << "QDebug enabled\n";
} else {
cout << "QDebug disabled!\n";
}
cout << "Start!\n";
qDebug() << "qStart!";
cerr << "print to stderr.\n";
qWarning() << "qWarning";
return 0;
}
构建步骤:
g++ -c -fPIC -I/usr/include/qt5 main.cpp -o main.o
g++ -fPIC main.o -L /usr/lib64 -lQt5Core -o testapp
在交互式 shell 中执行应用程序时,输出重定向按预期工作:
设置:
./testapp > out 2> err
输出:
>>cat out:
QDebug enabled
Start!
>>cat err:
qStart!
print to stderr.
qWarning
但是,如果应用程序作为 cronjob 执行,则它不起作用,缺少 qDebug() 和 qWarning() 的输出:
设置:
* * * * * username /home/username/temp/build/testapp 1> /home/username/temp/log/out 2> /home/username/temp/log/err
输出:
>>cat /home/username/temp/log/out
QDebug enabled
Start!
>>cat home/username/temp/log/err
print to stderr.
环境变量
env在interativeshell中的输出如下:
LS_COLORS=*long string*
SSH_CONNECTION=*censored*
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=*censored*
XDG_SESSION_ID=492
USER=username
SELINUX_ROLE_REQUESTED=
PWD=/home/username/temp/build
HOME=/home/username
SSH_CLIENT=*censored*
SELINUX_LEVEL_REQUESTED=
SSH_TTY=/dev/pts/0
MAIL=/var/spool/mail/username
TERM=xterm
SHELL=/bin/bash
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
LOGNAME=username
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/username/.local/bin:/home/username/bin
HISTSIZE=1000
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env
OLDPWD=/home/username/temp/build/logs
通过 cronjob 调用时 env 的输出如下:
LS_COLORS=*long string*
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=*censored*
XDG_SESSION_ID=995
USER=username
PWD=/home/username
HOME=/home/username
MAIL=/var/spool/mail/username
TERM=xterm
SHELL=/bin/bash
SHLVL=1
LOGNAME=username
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/username/.local/bin:/home/username/bin
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env
crontab 将输出和错误重定向到电子邮件地址。
在您的 crontab 条目中添加 >> /tmp/myscript.log 2>&1
。
看到这个answer
问题是 qt 的行为有所不同,具体取决于它是否认为它是 运行 在(交互式?)终端中。
One pitfall to be aware of: the destination of logging depends on an environment variable. If the variable QT_LOGGING_TO_CONSOLE is set to 1, the message functions will always log to the console. If set to 0, they will not log to the console, and will instead log to syslog, if enabled. When the environment variable is not set, the message functions log to a console if one is present (i.e. if the program is attached to a terminal). Thus, to ensure that the output of our example program goes to syslog, I set the environment variable to 0 within the program.
因此,从cron执行的qDebug、QWarning等的输出不是通过stderr输出,而是直接交给journald.
TL;DR: 快速修复:将 QT_LOGGING_TO_CONSOLE=1
添加到 /etc/crontab
.
.
PS:如果您需要使用 QDebug 调试问题,请注意:
- 注意这一点:https://bugzilla.redhat.com/show_bug.cgi?id=1227295
- 你可以添加
QT_LOGGING_DEBUG=1
作为环境变量来制作
执行期间 qt 输出日志记录行为发生变化。
我为此创建了一个复制样本:
#include <iostream>
#include <QtCore/QLoggingCategory>
#include <QtCore/QDebug>
#include <QtCore/QtCore>
using namespace std;
int main () {
int i;
QLoggingCategory::setFilterRules("*.debug=true\n");
QLoggingCategory LogO(NULL);
if (LogO.isDebugEnabled()) {
cout << "QDebug enabled\n";
} else {
cout << "QDebug disabled!\n";
}
cout << "Start!\n";
qDebug() << "qStart!";
cerr << "print to stderr.\n";
qWarning() << "qWarning";
return 0;
}
构建步骤:
g++ -c -fPIC -I/usr/include/qt5 main.cpp -o main.o
g++ -fPIC main.o -L /usr/lib64 -lQt5Core -o testapp
在交互式 shell 中执行应用程序时,输出重定向按预期工作:
设置:
./testapp > out 2> err
输出:
>>cat out:
QDebug enabled
Start!
>>cat err:
qStart!
print to stderr.
qWarning
但是,如果应用程序作为 cronjob 执行,则它不起作用,缺少 qDebug() 和 qWarning() 的输出:
设置:
* * * * * username /home/username/temp/build/testapp 1> /home/username/temp/log/out 2> /home/username/temp/log/err
输出:
>>cat /home/username/temp/log/out
QDebug enabled
Start!
>>cat home/username/temp/log/err
print to stderr.
环境变量
env在interativeshell中的输出如下:
LS_COLORS=*long string*
SSH_CONNECTION=*censored*
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=*censored*
XDG_SESSION_ID=492
USER=username
SELINUX_ROLE_REQUESTED=
PWD=/home/username/temp/build
HOME=/home/username
SSH_CLIENT=*censored*
SELINUX_LEVEL_REQUESTED=
SSH_TTY=/dev/pts/0
MAIL=/var/spool/mail/username
TERM=xterm
SHELL=/bin/bash
SELINUX_USE_CURRENT_RANGE=
SHLVL=1
LOGNAME=username
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/username/.local/bin:/home/username/bin
HISTSIZE=1000
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env
OLDPWD=/home/username/temp/build/logs
通过 cronjob 调用时 env 的输出如下:
LS_COLORS=*long string*
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOSTNAME=*censored*
XDG_SESSION_ID=995
USER=username
PWD=/home/username
HOME=/home/username
MAIL=/var/spool/mail/username
TERM=xterm
SHELL=/bin/bash
SHLVL=1
LOGNAME=username
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
XDG_RUNTIME_DIR=/run/user/1000
PATH=/usr/lib64/ccache:/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/username/.local/bin:/home/username/bin
LESSOPEN=||/usr/bin/lesspipe.sh %s
_=/usr/bin/env
crontab 将输出和错误重定向到电子邮件地址。
在您的 crontab 条目中添加 >> /tmp/myscript.log 2>&1
。
看到这个answer
问题是 qt 的行为有所不同,具体取决于它是否认为它是 运行 在(交互式?)终端中。
One pitfall to be aware of: the destination of logging depends on an environment variable. If the variable QT_LOGGING_TO_CONSOLE is set to 1, the message functions will always log to the console. If set to 0, they will not log to the console, and will instead log to syslog, if enabled. When the environment variable is not set, the message functions log to a console if one is present (i.e. if the program is attached to a terminal). Thus, to ensure that the output of our example program goes to syslog, I set the environment variable to 0 within the program.
因此,从cron执行的qDebug、QWarning等的输出不是通过stderr输出,而是直接交给journald.
TL;DR: 快速修复:将 QT_LOGGING_TO_CONSOLE=1
添加到 /etc/crontab
.
.
PS:如果您需要使用 QDebug 调试问题,请注意:
- 注意这一点:https://bugzilla.redhat.com/show_bug.cgi?id=1227295
- 你可以添加
QT_LOGGING_DEBUG=1
作为环境变量来制作 执行期间 qt 输出日志记录行为发生变化。