命令 'startx' 仅在终端中输入时才有效,而不是从 bash 脚本输入时有效



我在/etc/udev.rules.d/中写了一个规则,如果设备插入到我的Raspberry pi 4上,它会运行一个bash脚本'/home/pi/startx.sh'。这个规则是有效的,在某种意义上,如果我在脚本中写

#!/bin/bash
touch test.txt

test.txt文件实际上是在每次插入键盘时创建的。现在我想让这个脚本以用户'pi'的身份运行startx命令。在实践中,我希望Raspberry以控制台模式启动,并且只有在通过脚本startx.sh插入该设备时才启动'pi'用户的桌面。

现在如果我在脚本中写

#!/bin/bash
startx

它不工作,并且pi的Xorg桌面无法启动。

如果我尝试从ssh运行它,它会说(好吧,我不在乎通过ssh启动它,这只是一个尝试):Parse_vt_settings/dev/tty0 (permission denied)

真正荒谬的事情是,如果我在监视器前从键盘上运行startx命令,startx工作没有问题(总是作为用户pi)。更重要的是,如果我从控制台中运行./startx.sh脚本,当我在监视器前时,它可以完美地工作。

重要的是要指定我希望桌面以用户'pi'启动,而不是以root或其他用户启动。所以命令sudo startx是不合适的(它的工作显然是给我另一个桌面,不是pi的)。

我也不想更改tty, video等的任何权限,因为如果它在控制台中工作,当我在显示器前时,我不明白为什么它不能从bash脚本中工作。

OS: Raspbian GNU/Linux 10 (buster)树莓派4

我试着这样修改脚本:

#!/bin/bash -l
startx

#!/bin/bash
sudo -u pi startx

#!/bin/bash -l
sudo -u pi startx

#!/bin/bash
sudo -i -u pi xinit

没有任何结果。

">startx";将启动桌面,只要桌面还没有运行.

你面对的是

  • 与之前的Desktop实例冲突,或者
  • 您没有正确识别系统认为是控制台的设备,而桌面必须是控制台。,或
  • 你没有正确定义双头Pi的设备,或者
  • 目标设备的配置与预期的X显示不一致。

帮助您识别进程父进程和依赖,下面是一个脚本(重用/修改),用于在层次结构树中显示流程。最初的程序被简单地称为pt。我调用我自己的pt.sh.

#!/bin/sh
##################################################################################
### 
### $Id: pt.sh,v 2.4 2022/08/17 22:27:05 root Exp $
### 
### Script to print a process tree on stdout.
###     - easy to see relationships between processes with this script
### Synt: pt [opts] [startPID]
### Opts:   -h,H,-V : help,HELP,version
###     -w width: screen width
###     -o type : output type: 1, 2, or 3 (def 3)
### Parm: startPID: show tree starting at this PID (def: 1)
### 
### @(#) pt - display Process Table "Tree"
### 
### Original Author:  William J. Duncan (prior to May 7 1996)
### 
### Synopsis:
###   pt [opts] [startPID] |  less      # (or whatever your fav pager is)
### 
### Notes:
###   - all recent implementations of awk I have seen have recursion.
###     It is a requirement.  This is a nice little example of using
###     recursion in awk.
### 
###   - under bsd, there was no real happy mix of options which
###     would pick up a user's name, and do everything else we wanted.
###     (eg. need to pick up PPID for example)
###     So we need to do a separate search through the passwd entries
###     ourselves and build a lookup table, or alternatively run ps
###     twice.
### 
###   - notice the ugliness of 3 separate sets of quotes required in
###     the line:
###       while ("'"$GETPASSWD"'" | getline > 0)
### 
###     The inside pair of quotes keeps the 2 tokens for the command
###     together.  The pair of single quotes escapes from within the
###     awk script to the "outside" which is the shell script.  This
###     makes the shell variable "$GETPASSWD" available for use with-
###     in the awk script as a literal string.  (Which is the reason
###     for the outside pair of double quotes.)
### 
###   - This is the general format of including awk scripts within
###     the shell, and passing ENVIRONMENT variables down.    -wjd
### 
##################################################################################
##################################################################################
###
### Mods by E. Marceau, Ottawa, Canada
### 
###   - Added logic to determine max length of username for proper display of that field
### 
##################################################################################
TMP=/tmp/`basename "$0" ".sh" `.$$
set -u
## Constants
rcsid='$Id: pt.sh,v 2.4 2022/08/17 22:27:05 root Exp $'
P=`basename $0`;
## This command should list the password file on on "all" systems, even
## if YP is not running or 'ypcat' does not exist.
## List the local password file first because the UIDS array is assigned
## such that later entries override earlier entries.
if [ -z "`which ypcat 2>>/dev/null `" ]
then
GETPASSWD="(cat /etc/passwd)"
else
GETPASSWD="(ypcat passwd 2>/dev/null)"
fi
## Name: usage;   Desc: standard usage description function
usage() { awk 'NF==0{if(n++=='${1:-0}')exit}0==0'<$0; }
maxWidth=0
## check for options
set -- `getopt ehHVw:o: ${*:-}`
test $? -ne 0  &&  usage 0  &&  exit 9
for i in $*; do
case $i in
-e)     maxWidth=1    ;  COLS=512 ; shift   ;;
-h)     usage 0 && exit 9                       ;;
-H)     usage 1 && exit 9                       ;;
-V) echo "${P} ${rcsid}"|cut -d' ' -f1,4-5; exit;;
-w) COLS=$2       ;  shift 2        ;;
-o)     outtype=$2    ;  shift 2        ;;
--)     shift         ;  break          ;;
esac
done
## initialize
startpid="${1:-1}"
SYSTEM=${SYSTEM:-`uname`}
outtype="${outtype:-3}"
case ${SYSTEM} in
#    XENIX)          # or any other sys5 i think
#        PS=/bin/ps
#        AWK=/bin/awk
#        PSFLAGS=-ef
#        SYSTEM=sys5
#        SIZE='/bin/stty size'
#        ;;
#    SunOS)          # bsd flavours of ps
#        os=`uname -r | cut -c1`
#        PS=/bin/ps
#        AWK=nawk
#   if test "$os" = "4"; then
#           PSFLAGS=-axjww
#           SYSTEM=bsd
#           SIZE='/bin/stty size'
#   else
#           PSFLAGS=-ef
#           SYSTEM=sys5
#           SIZE='/usr/ucb/stty size'
#   fi
#   ;;
#    HP-UX)
#        PS=/bin/ps
#       AWK=/usr/bin/awk
#        PSFLAGS=-ef
#        SYSTEM=sys5
#        SIZE='/bin/stty size'
#        ;;
Linux)
PS=/bin/ps
AWK=awk
PSFLAGS=-axjww
SYSTEM=bsd
SIZE='/bin/stty size'
;;
*)
PS=/bin/ps
AWK=awk
PSFLAGS=-axjww
SYSTEM=bsd
SIZE='/bin/stty size'
;;
esac
COLShere=`${SIZE} | awk '{print $2}' `
COLS=${COLS:-$COLShere}
COLS=${COLS:-80}
echo "t    [1] ${COLS}"
${PS} ${PSFLAGS} | 
${AWK} -v maxWidth="${maxWidth}" 'BEGIN{  lowestPID=9999 ;
FS = ":" ;
while ("'"${GETPASSWD}"'" | getline > 0){
UIDS[ $3 ] = $1 ;
} ;
UIDS[ 0 ] = "root" ;                # fix for "extra" root accounts
for ( var in UIDS ){
lenT=length( UIDS[var] ) ;
if ( lenT > lenM ){
lenM=lenT ;         # longest=UIDS[var] ;
} ;
} ;
printf("%6s %6s %4s  %-"lenM"s %sn", "PID", "PPID", "TTY", "USER", "COMMAND" ) ;
FS = " " ;
COLS='${COLS}' ;
SYSTEM="'${SYSTEM}'" ;
if (SYSTEM == "sys5"){
fpid   = 2 ;
fppid  = 3 ;
fuid   = 1 ;
}else{
if (SYSTEM == "bsd"){
fpid   = 2 ;
fppid  = 1 ;
fuid   = 8 ;
} ;
} ;
outtype ="'${outtype}'" ;
if (outtype == 1){
SPACES=".............................................................................................." ;
SPREAD=1 ;
CMD_PREFIX=" " ;
}else{
if (outtype == 2){
SPACES="||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||" ;
SPREAD=1 ;
CMD_PREFIX="" ;
}else{
SPACES="| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |" ;
SPREAD=2 ;
CMD_PREFIX="" ;
} ;
} ;

} ;

NR==1 { title = $0 ; next } ;
# All others
{
if ( $fpid < lowestPID ){ lowestPID=$fpid ; } ;
LINE[ $fpid  ] = $0  ;                      # Line indexed by PID
PCNT[ $fppid ]++  ;                         # Index into PPID
PPID[ $fppid, PCNT[$fppid] ] = $2 ;         # Parent to Children unique
INDENT=0 ;
} ;
function doprint(s, a, name, i, nf, tty, cmd){
# the splitting and complications here are mostly for
# sys5, which a different number of fields depending on STIME
# field.  Argh.
nf = split(s,a) ;
for (i=7; i <= nf; i++){
if (a[i] ~ /[0-9]:[0-9][0-9]/){
break   # set i here
} ;
} ;
for (i++ ; i <= nf; i++){
name = name " " a[i] ;
} ;
if (a[fuid] in UIDS){
a[fuid] = UIDS[a[fuid]] ;             # if username found
} ;
if (SYSTEM == "bsd"){                    # if bsd
tty = a[5] ;
}else{                                    # sys5 2 possible formats
tty = (a[5] ~ /^[0-9]+:/) ? a[6] : a[7] ;
} ;
cmd = substr(SPACES,1,INDENT*SPREAD) CMD_PREFIX substr(name,2) ;
#if ( length(cmd) > COLS-27 && maxWidth == 0 ){
if ( length(cmd) > COLS-27 ){
cmd = substr(cmd,1,COLS-27) ;
} ;
printf("%6d %6d %4s  %-"lenM"s %sn", a[fpid], a[fppid], substr(tty,length(tty)-1), a[fuid], cmd ) ;
} ;
function dotree(pid) {      # recursive
if (pid == 0) return
doprint(LINE[ pid ])
INDENT++
while (PCNT[pid] > 0) {
dotree(PPID[ pid, PCNT[pid] ] ) ;   # recurse
delete PPID[ pid, PCNT[pid] ] ;
PCNT[pid]-- ;
} ;
INDENT-- ;
} ;
END{
if ( lowestPID > startpid ){ startpid=lowestPID ; } ;
dotree('${startpid}') ;
}' >${TMP}.initial

###########################################################################################################################
###
### Additional coding to present results with PID correctly sorted along with associated children also in sorted order.
###
###########################################################################################################################
head -1 ${TMP}.initial >${TMP}.head
tail --lines=+2 ${TMP}.initial | sort --key=1,1n --key=2,2n >${TMP}.remainder
cat ${TMP}.head
while [ true ]
do
line=`awk '{ if ( NR == 1 ){ print $0 } ; exit }' <${TMP}.remainder `
first=`echo "${line}" | awk '{ print $1 }' `
echo "${line}"
#get children
tail --lines=+2 ${TMP}.remainder | awk -v pid="${first}" '{ if ( $2 == pid ){ print $0 } ; }' >${TMP}.next
tail --lines=+2 ${TMP}.remainder | awk -v pid="${first}" '{ if ( $2 != pid ){ print $0 } ; }' >${TMP}.others
cat ${TMP}.next ${TMP}.others >${TMP}.remainder
if [ ! -s ${TMP}.remainder ] ; then  break ; fi
done        ###  >${TMP}.new ;cat ${TMP}.new

exit 0
exit 0
exit 0

最新更新