我在/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