Context:
上下文:
I want to add a conditional startup script to LightDM that detects screen resolution and if it is too high, it scales the screen via xrandr.
我想给LightDM添加一个有条件的启动脚本,它可以检测屏幕分辨率,如果分辨率太高,它会通过xrandr来缩放屏幕。
Script (irrelevant to this question):
脚本(与此问题无关):
#!/bin/bash
# If the display has higher resolution than X_THR x Y_THR,
# it will be scaled by a factor of SCALE x SCALE.
X_THR=3840
Y_THR=2160
SCALE=0.5
# First, check if exactly one display is connected.
# Otherwise, we don't really know what's happening and
# the script should terminate without making changes.
if [ "$(xrandr | grep -w connected | wc -l)" -ne 1 ];
then
echo "Not adjusting screen settings automatically,\
detected $(xrandr | grep -w connected | wc -l)\
screens";
exit 0;
fi
# Note that the screen may either be marked as "primary"
# or not. By treating "primary" as a field separator in AWK
# we handle both cases.
read display_name resolution <<<\
"$(xrandr | grep -w connected | awk -F'\\sprimary\\s|[ \\+]' '{print $1,$3}')"
read x_dim y_dim <<<\
"$(echo $resolution | awk -F'x' '{print $1,$2}')"
if [ "$x_dim" -ge "$X_THR" -a "$y_dim" -ge "$Y_THR" ];
then
echo "Updating X server scale."
xrandr --output $display_name --scale "$SCALE"x"$SCALE"
fi
LightDM configuration file (/etc/lightdm/lightdm.conf.d/99-labdoo.conf):
LightDM配置文件(/etc/lightdm/lightdm.con.d/99-Labdoo.conf):
[Seat:*]
user-session=LXDE
display-setup-script=/opt/labdoo/setup/startup_scripts/screen_scaling.sh || true
What happened:
发生了什么事:
By a mistake, I changed the preamble in the script from #!/bin/bash
to #!/bin/sh
, which resulted in the script failing with some syntax error.
由于错误,我将脚本中的前言从#!/bin/bash更改为#!/bin/sh,这导致脚本失败,并出现一些语法错误。
Expected behaviour:
I would expect LightDM to ignore the failure of the script thanks to the || true
in display-setup-script
.
预期行为:我希望LightDM忽略脚本失败,这要归功于Display-Setup-SCRIPT中的||TRUE。
Actual behaviour:
LightDM failed to load the greeting screen. In /var/log/lightdm/lightdm.log I saw a line:
Exit status of /opt/labdoo/setup/startup_scripts/screen_scaling.sh || true: 1
实际行为:LightDM无法加载问候语屏幕。在/var//opt/labdoo/setup/startup_scripts/screen_scaling.sh/lightdm/lightdm.log中,我看到一行:退出状态of LightLog||TRUE:1
How can the exit status be 1?
退出状态怎么可能是%1?
更多回答
Likely the value of display-setup-script
inside config does not evaluate as shell expression (does not understand || true
at all and just takes name of executable to run) ? In such case you'd need to handle errors inside the script (or wrap script in another script).
很可能配置中的Display-Setup-SCRIPT的值不会作为外壳表达式计算(根本不理解||TRUE,只接受可执行文件的名称来运行)?在这种情况下,您需要处理脚本内部的错误(或将脚本包装在另一个脚本中)。
What blami says. || true
is a shell construct. It only matters if your string is run through system()
, not if it's directly executed. The bash tag isn't relevant here because the problem here is that neither bash or any other shell is being invoked at all.
布拉米说的话。|TRUE为外壳构造。只有当您的字符串通过system()运行时才重要,而不是直接执行。Bash标记在这里并不重要,因为这里的问题是bash或任何其他外壳都没有被调用。
Now, if you had used display-setup-script=/bin/sh -c '/opt/labdoo/setup/startup_scripts/screen_scaling.sh || true'
, that would have treated || true
as syntax.
现在,如果您使用Display-Setup-Scrip=/bin/sh-c‘/opt/labdoo/setup/startup_scripts/screen_scaling.sh||TRUE’,就会将||TRUE视为语法。
BTW, <<<
is the most obvious syntax you're using that sh
isn't guaranteed to support. And test -a
is marked obsolescent (look for the [OB]
markers in the standard document); use either the POSIX syntax if [ "$x_dim" -lt "$X_THR" ] && [ "$y_dim" -lt "$Y_THR" ]
or the bash syntax if (( x_dim < X_THR && y_dim < Y_THR ))
顺便说一句,<是您正在使用的最明显的语法,sh不保证支持它。和test-a被标记为已过时(在标准文档中查找[OB]标记);如果[“$x_dim”-lt“$X_Thr”]&&[“$y_dim”-lt“$Y_Thr”],则使用POSIX语法;如果((x_dim
I'm tempted to argue that this is more a question about lightdm's config file format than a question about shells or programming, and thus that it would be better placed over on Super User or Unix & Linux -- there's a reason we don't have a lightdm tag on our site (and while the answer involved a lot of C, I can't really justify calling it a C question).
我想争辩说,这更多的是一个关于lightdm的配置文件格式的问题,而不是一个关于外壳或编程的问题,因此它更适合放在超级用户或Unix和Linux上--我们的站点上没有lightdm标记是有原因的(虽然答案涉及很多C语言,但我不能真正证明它是一个C问题)。
优秀答案推荐
LightDM doesn't use a shell at all when it invokes display-setup-script
, but rather performs its own shell-like parsing. Therefore || true
is passed as two extra arguments ('||'
and 'true'
, which you'll see if you do something like echo "Called as: ${0@Q} ${*@Q}" >&2
in your script), not treated as syntax.
LightDM在调用显示-设置-脚本时根本不使用外壳,而是执行自己的类似外壳的解析。因此,||TRUE被作为两个额外的参数(‘||’和‘TRUE’传递,如果您在脚本中执行类似ECHO“Called as:${0@q}${*@q}”>&2的操作,就会看到这一点),而不是将其视为语法。
Processing this configuration starts in lightdm/src/seat.c
:
处理此配置在lightdm/src/seat.c中开始:
if (script && !run_script (seat, display_server, script, NULL))
{
l_debug (seat, "Stopping display server due to failed setup script");
display_server_stop (display_server);
return;
}
Following the definition of run_script
, in lightdm/src/process.c
, we see LightDM trying to parse the command line itself instead of passing it to a shell to parse:
按照运行脚本的定义,在lightdm/src/process.c中,我们看到LightDM试图解析命令行本身,而不是将其传递给外壳进行解析:
if (!g_shell_parse_argv (priv->command, &argc, &argv, &error))
{
g_warning ("Error parsing command %s: %s", priv->command, error->message);
return FALSE;
}
...and then, below, directly executing the child:
...然后,在下面,直接处决这个孩子:
execvp (argv[0], argv);
No shell is involved, so shell syntax is not honored.
由于不涉及外壳,因此不支持外壳语法。
更多回答
我是一名优秀的程序员,十分优秀!