如何以 root 身份运行 Perl 脚本但仍会影响用户 gconf 设置

Posted

技术标签:

【中文标题】如何以 root 身份运行 Perl 脚本但仍会影响用户 gconf 设置【英文标题】:How can I run a Perl script as root yet still affect user gconf settings 【发布时间】:2011-04-22 00:02:34 【问题描述】:

新问题:我正在尝试制作一个统一的脚本,根据我的喜好初始化新的 Ubuntu 安装,它必须在 sudo 下运行才能安装软件包,但使用 gconftool-2 影响 gconf 设置依赖于 dbus 会话仅在脚本中简单更改 UID 的方法无法正确处理。有人知道如何做到这一点吗?

旧查询:我正在编写一个 Perl 脚本,以便在首次安装新的 Ubuntu 时执行。这是为了方便添加存储库、安装包和设置 gconf 设置。我的问题是权限。要安装软件包,我需要将脚本作为 sudo 执行,然后 gconftool-2 调用作用于 root 用户而不是我的个人用户。

【问题讨论】:

【参考方案1】:

您可以通过使用POSIX::setuid() 更改uid 来更改脚本中间的uid(请参阅perldoc POSIX):

use POSIX 'setuid';

# call cpan to install modules...

POSIX::setuid($newuid);

# ... continue with script

【讨论】:

这看起来很有希望。结合 getlogin() 来获取登录名,并结合 getpwnam(name) 来获取我的 uid,我希望它应该可以工作。 遗憾的是,这还不够。在阅读了更多内容之后,gconftool-2 以某种方式检查 dbus 以发挥其魔力。这远远超出我的想象。我将编辑我的问题,但如果进展不顺利,我将不得不满足自己的两个脚本,一个在 sudo 下运行,一个以用户身份运行。 我确实需要 POSIX::setuid 命令,但我更需要环境变量,所以我投票给你,但不正确。没有难过的感觉!【参考方案2】:

您可以再次使用 sudo 来删除您的 root 权限,例如:

sudo -u 'your_username' gfconftool-2

【讨论】:

我已经做了一些测试,但我不确定它是否有效,尽管它看起来确实应该! 只是清理一些东西。同样,这不起作用的原因是上面的 ENV 变量没有设置。尝试perl -E 'say $< . "\n" . $ENV'DBUS_SESSION_BUS_ADDRESS'' 作为用户,在sudosudo -u username 下查看差异【参考方案3】:

经过大量阅读和反复试验,当您以 root 身份运行脚本时,似乎缺少的是未设置 DBUS_SESSION_BUS_ADDRESS 环境变量。在设置 gconf 设置之前,必须设置此项并将 uid 更改为用户的。这是我用来尝试的测试脚本。最后运行一个或另一个系统调用来切换窗口按钮顺序。以用户或 root (sudo) 身份尝试该脚本以查看它是否有效。

#!/usr/bin/perl

use strict;
use warnings;

use POSIX;

# get the user's name (as opposed to root)
my $user_name = getlogin();
# get the uid of the user by name
my $user_uid = getpwnam($user_name);
print $user_name . ": " . $user_uid . "\n";

my %dbus;
# get the DBUS machine ID
$dbus'machine_id' = qxcat /var/lib/dbus/machine-id;
chomp( $dbus'machine_id' );
# read the user's DBUS session file to get variable DBUS_SESSION_BUS_ADDRESS
$dbus'file' = "/home/" . $user_name . "/.dbus/session-bus/" . $dbus'machine_id' . "-0";
print "checking DBUS file: " . $dbus'file' . "\n";
if (-e $dbus'file')  
  open(my $fh, '<', $dbus'file') or die "Cannot open $dbusfile";
  while(<$fh>) 
    if ( /^DBUS_SESSION_BUS_ADDRESS=(.*)$/ ) 
      $dbus'address' = $1;
      print "Found DBUS address: " . $dbus'address' . "\n";
    
  
 else 
  print "cannot find DBUS file";


# set the uid to the user's uid not root's
POSIX::setuid($user_uid);
# set the DBUS_SESSION_BUS_ADDRESS environment variable
$ENV'DBUS_SESSION_BUS_ADDRESS' = $dbus'address';

my $command1 = 'gconftool-2 --set "/apps/metacity/general/button_layout" --type string "menu:maximize,minimize,close"';
my $command2 = 'gconftool-2 --set "/apps/metacity/general/button_layout" --type string "menu:minimize,maximize,close"';
system($command1);
## or
#system($command2);

注意:得到了一些有用的信息here。

【讨论】:

以上是关于如何以 root 身份运行 Perl 脚本但仍会影响用户 gconf 设置的主要内容,如果未能解决你的问题,请参考以下文章

以管理员身份运行 cgi perl 脚本

如何以用户而不是 root 用户身份运行 cron 作业 [关闭]

如何以非 root 用户身份使用 CPAN?

以 root 身份运行结构脚本

以root身份在脚本中间运行命令[重复]

以root身份运行python脚本