startx analyze

2023-10-26

1       xinit

在说明startx之前,我想我们应该先了解一下xinit。因为startx就是通过调用xinit启动X的。

1.1    功能

当我们安装了Ubuntu后,默认就已经安装了xinit,它位于/usr/bin下。xinit是一个二进制文件,并非是一个脚本。它的主要功能是启动一个X服务器,同时启动一个基于X的应用程序。

1.2    用法

xinit的用法为:xinit [[client] options ] [-- [server] [display] options]。其中client用于指定一个基于X的应用程序,client后面的options是传给这个应用程序的参数,server是用于指定启动哪个X服务器,一般为/usr/bin/X/usr/bin/Xorgdisplay用于指定display number,一般为0,表示第一个displayoption为传给server的参数。

 

如果不指定clientxinit会查找HOME(环境变量)目录下的.xinitrc文件,如果存在这个文件,xinit直接调用execvp函数执行该文件。如果这个文件不存在,那么client及其options为: xterm -geometry +1+1 -n login -display :0 

 

如果不指定serverxinit会查找HOME(环境变量)目录下的.xserverrc文件,如果存在这个文件,xinit直接调用execvp函数执行该文件。如果这个文件不存在,那么server及其display为: X :0。如果系统目录中不存在X命令,那么我们需要在系统目录下建立一个名为X的链接,使其指向真正的X server命令(Ubuntu下为Xorg)。

 

1.3    例子

下面是几个关于xinit应用的例子:

1)      xinit /usr/bin/xclock -- /usr/bin/X :0

该例子将启动X server, 同时将会启动xclock。请注意指定client或server时,需要用绝对路径,否则xinit将因无法区别是传给xterm或server的参数还是指定的client或server而直接当成是参数处理。

2)      HOME下新建.xinitrc文件,并加入以下几行:

         xsetroot -solid gray &
         xclock -g 50x50-0+0 -bw 0 &
         xterm -g 80x24+0+0 &
         xterm -g 80x24+0-0 &
         twm

xinit启动时,它会先启动X server,然后启动一个clock,两个xterm,最后启动窗口管理器twm。

请注意:

最后一个命令不能后台运行,否则所有命令都后台运行的话xinit就会返回退出,同样的,除最后一个命令外都必须后台运行,否则后面的命令将只有在该命令退出后才能运行。

 

1.4    分析

看到这里,眼尖的人或许早以看出xinit的功能完全可以由脚本来实现,例如要启动X Server 和一个xterm,就像xinit默认启动的那样,只需要在新建一个脚本或在rc.local中加入:

X&

export DISPLAY=:0.0

xterm

这个实现完全正确,然而却并没有完全实现xinit所具有的功能,xinit所有的一项功能就是当最后一个启动的client(如上面第二个例子中的twm窗口管理器)退出后,X服务器也会退出。而我们的脚本实现中当我们退出xterm后并不会退出X server


 

2       startx脚本

用过linux的人基本上都知道linux下有个命令叫做startx,那么它到底是怎么实现的呢?

2.1    功能

当我们在终端下想启动图形界面时,我们都会通过输入startx来实现,该命令可以启动一个Xserver,而且可以启动一个漂亮的图形界面(Ubuntu下,我装的是gnome)。

2.2    用法

Startx的用法和xinit的基本一样:startx [ [ client ] options ... ] [ -- [ server ] options ... ]。为什么呢?这是因为startx其实就是一个脚本,它启动X server就是通过调用xinit命令实现的,startx的参数将全部传给xinit。因此,这些参数的意义和xinit的参数是一样的。

2.3    例子

下面是两个关于startx命令的简单例子:

1)  startx -- -depth 16

该例子主要是以16位色启动X 服务器。

2)  startx -- -dpi 100

该例子主要是以100的dpi启动X 服务器。

2.4    分析

下面我们来分析一下startx脚本。startx脚本位于/usr/bin下,直接用vim打开我们可以看到它的具体实现如下:

 

#!/bin/bash #注意:该脚本用的是bash shell解析的

 

# $Xorg: startx.cpp,v 1.3 2000/08/17 19:54:29 cpqbld Exp $

#

# This is just a sample implementation of a slightly less primitive

# interface than xinit. It looks for user .xinitrc and .xserverrc

# files, then system xinitrc and xserverrc files, else lets xinit choose

# its default. The system xinitrc should probably do things like check

# for .Xresources files and merge them in, startup up a window manager,

# and pop a clock and serveral xterms.

#

# Site administrators are STRONGLY urged to write nicer versions.

#

# $XFree86: xc/programs/xinit/startx.cpp,v 3.16tsi Exp $

 

#下面主要是对一些变量进行赋值。

userclientrc=$HOME/.xinitrc

sysclientrc=/etc/X11/xinit/xinitrc

 

 

userserverrc=$HOME/.xserverrc

sysserverrc=/etc/X11/xinit/xserverrc

defaultclient=xterm

defaultserver=/usr/bin/X

defaultclientargs=""

defaultserverargs=""

clientargs=""

serverargs=""

 

#下面的语句主要是说:如果$HOME/.xinitrc文件存在,并且不是一个目录,那么就将defaultclientargs赋值为$HOME/.xinitrc,否则,如果/etc/X11/xinit/xinitrc存在并且不是一个目录,就将defaultclientargs赋值为/etc/X11/xinit/xinitrc。

 

if [ -f $userclientrc ]; then

    defaultclientargs=$userclientrc

elif [ -f $sysclientrc ]; then

    defaultclientargs=$sysclientrc

 

 

 

 

 

 

fi

 

#下面的语句主要是说:如果$HOME/.xserverrc文件存在,并且不是一个目录,那么就将defaultclientargs赋值为$HOME/.xserverrc,否则,如果/etc/X11/xinit/xserverrc存在并且不是一个目录,就将defaultclientargs赋值为/etc/X11/xinit/xserverrc。

 

if [ -f $userserverrc ]; then

    defaultserverargs=$userserverrc

elif [ -f $sysserverrc ]; then

    defaultserverargs=$sysserverrc

fi

#将whoseargs变量赋值为字符串“client”,表示当前解析的指定client的参数。

whoseargs="client"

#当startx的一个参数不为空时就进入while循环。

while [ x"$1" != x ]; do

    case "$1" in

    # '' required to prevent cpp from treating "/*" as a C comment.

    /''*|/./''*)

 if [ "$whoseargs" = "client" ]; then

     if [ x"$clientargs" = x ]; then

  client="$1" #解析出了用户指定的Client程序

     else

  clientargs="$clientargs $1"  #解析出了Client的参数

     fi

 else

     if [ x"$serverargs" = x ]; then

  server="$1"  #解析出了用户指定的X Server程序

     else

  serverargs="$serverargs $1" #解析出了X Server的参数

     fi

 fi

 ;;

    --)    #遇到“- -”就解析server

 whoseargs="server"

 ;;

    *)

 if [ "$whoseargs" = "client" ]; then

     clientargs="$clientargs $1"

 else

     # display must be the FIRST server argument

     if [ x"$serverargs" = x ] && /

   expr "$1" : ':[0-9][0-9]*$' > /dev/null 2>&1; then

  display="$1" #解析出display

     else

  serverargs="$serverargs $1"

     fi

 fi

 ;;

    esac     #case语句结束

shift  #将参数列表左移一位,即解析下个参数.

done

 

# process client arguments

if [ x"$client" = x ]; then #如果client变量为空,即用户没有指定client。

    # if no client arguments either, use rc file instead

    if [ x"$clientargs" = x ]; then #如果用户没有指定client参数 就将client设为前面设定的默认的rc文件(为$HOME/.xinitrc,或/etc/X11/xinit/xinitrc)

 client="$defaultclientargs"

    else

 client=$defaultclient #如果用户指定了client参数,就将client设定为xterm

    fi

fi

 

# process server arguments

if [ x"$server" = x ]; then #如果server变量为空,即用户没有指定server。

    # if no server arguments or display either, use rc file instead

    if [ x"$serverargs" = x -a x"$display" = x ]; then #如果serverargs为空,并且display为空,就将server设为前面设定的默认的rc文件(为$HOME/. xserverrc,或/etc/X11/xinit/ xserverrc)

 server="$defaultserverargs"

    else

 server=$defaultserver #如果用户指定了serverargs或display,就将server设定为/usr/bin/X

    fi

fi

 

if [ x"$XAUTHORITY" = x ]; then #如果环境变量XAUTHORITY为空,就设定为$HOME/.Xauthority

    XAUTHORITY=$HOME/.Xauthority

    export XAUTHORITY

fi

 

removelist=

 

# set up default Xauth info for this machine

 

# check for GNU hostname

if hostname --version > /dev/null 2>&1; then #如果hostname命令存在

       if [ -z "`hostname --version 2>&1 | grep GNU`" ]; then #如果hostname –version中不包含GNU 就将hostname变量设定为命令hostname –f返回的字符串。

  hostname=`hostname -f`

       fi

fi

 

if [ -z "$hostname" ]; then #如果hostname长度为0,就将hostname变量设定为命令hostname返回的字符串。

hostname=`hostname`

fi

 

authdisplay=${display:-:0}

 

mcookie=`/usr/bin/mcookie`

 

 

 

 

 

 

 

dummy=0

 

# create a file with auth information for the server. ':0' is a dummy.

xserverauthfile=`mktemp -p /tmp serverauth.XXXXXXXXXX`

trap "rm -f $xserverauthfile" HUP INT QUIT ILL TRAP KILL BUS TERM

xauth -q -f $xserverauthfile << EOF

add :$dummy . $mcookie

EOF

serverargs=${serverargs}" -auth "${xserverauthfile}

 

# now add the same credentials to the client authority file

# if '$displayname' already exists do not overwrite it as another

# server man need it. Add them to the '$xserverauthfile' instead.

for displayname in $authdisplay $hostname$authdisplay; do

     authcookie=`xauth list "$displayname" /

       | sed -n "s/.*$displayname[[:space:]*].*[[:space:]*]//p"` 2>/dev/null;

    if [ "z${authcookie}" = "z" ] ; then

        xauth -q << EOF

add $displayname . $mcookie

EOF

 removelist="$displayname $removelist"

    else

        dummy=$(($dummy+1));

        xauth -q -f $xserverauthfile << EOF

add :$dummy . $authcookie

EOF

    fi

done

echo "client=$client,clientargs=$clientargs,server= $server, display= $display, serverargs=$serverargs"

 

#下面的语句通过xinit启动X server和Clients。

xinit $client $clientargs -- $server $display $serverargs

 

 

if [ x"$removelist" != x ]; then

    xauth remove $removelist

fi

if [ x"$xserverauthfile" != x ]; then

    rm -f $xserverauthfile

fi

 

 

 

 

 

if command -v deallocvt > /dev/null 2>&1; then

    deallocvt  #释放所有未使用的虚拟终端的核心内存和数据结构

fi

 

 

2.5    总结

由以上对startx脚本的分析,我们可以知道:startx将会先解析用户的参数,如果该用户指定了该参数(即解析结果不为空),那么startx就会以该参数来启动xinit,否则就会解析(与其说是解析,还不如说是执行)$HOME目录下的rc文件,如果该文件不存在,就会解析系统目录下(/etc/X11/xinit/)的rc文件,如果这个文件也不存在,那startx就将以默认的clientxterm)和server/usr/bin/X)为参数来启动xinit


 

3       startx默认启动过程

通过以上对startx脚本的分析,我们知道了startx的基本的启动流程,但是到目前为止,我们还不知道仅仅在终端输入startx是怎么样启动gnome那漂亮的桌面的,下面我们来看一下其启动过程。

3.1    startx的几种启动方式

由对startx脚本的分析,我们可以知道startx主要有三种启动方式:

a)、一种是自己指定要启动的clientserver, 例如:startx /usr/bin/xclock -- /usr/bin/X :0

b)、一种是通过在$HOME下新建.xinitrc文件来指定要启动的多个client.xserverrc来指定要启动的server(注意:这两个文件本来是不存在的);

c)、还有一种是直接输入startx而不指定参数,这也就是我们启动gnome桌面的方法。这里

 

我们主要介绍最后一种启动方法。

 

在c这种启动方法中,我们可以知道,startx脚本会先去看系统目录(/etc/X11/xinit/)下的rc文件是否存在,如果不存在就会用默认的xterm/usr/bin/X来启动xinit。显然,startx启动的不是xterm,而是gnome桌面,因此gnome的启动是通过系统文件/etc/X11/xinit/xinitrc来指定的。

 

/etc/X11/xinit/xinitrc文件的内容如下所示:

 

#!/bin/bash  #注意:该脚本用的是bash shell解析的

 

# $Xorg: xinitrc.cpp,v 1.3 2000/08/17 19:54:30 cpqbld Exp $

 

# /etc/X11/xinit/xinitrc

#

# global xinitrc file, used by all X sessions started by xinit (startx)

 

# invoke global X session script

. /etc/X11/Xsession  #在当前这个shell环境中执行Xsession脚本

 

 

因此,gnome的启动应该在Xsession里。

 

而X Server的启动则是通过系统文件/etc/X11/xinit/xserverrc来指定的,这个文件的内容为:

 

#!/bin/sh #注意:该脚本用的是Bourne shell解析的

 

# $Id: xserverrc 189 2005-06-11 00:04:27Z branden $

 

exec /usr/bin/X11/X -nolisten tcp

 

3.2      Xsession

下面是Xsession脚本的内容:

#!/bin/sh #注意:该脚本用的是Bourne shell解析的

#

# /etc/X11/Xsession

#

# global Xsession file -- used by display managers and xinit (startx)

 

# $Id: Xsession 967 2005-12-27 07:20:55Z dnusinow $

 

set –e #打开errexit选项,该选项表示:如果下面有命令返回的状态非0,则退出程序。

 

PROGNAME=Xsession

 

#下面四个是信息输出函数,可以不管

message () {

  # pretty-print messages of arbitrary length; use xmessage if it

  # is available and $DISPLAY is set

  MESSAGE="$PROGNAME: $*"

  echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2

  if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then

    echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -

  fi

}

 

message_nonl () {

  # pretty-print messages of arbitrary length (no trailing newline); use

  # xmessage if it is available and $DISPLAY is set

  MESSAGE="$PROGNAME: $*"

  echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2;

  if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then

    echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -

  fi

}

 

errormsg () {

  # exit script with error

  message "$*"

  exit 1

}

 

internal_errormsg () {

  # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message

# One big call to message() for the sake of xmessage; if we had two then

  # the user would have dismissed the error we want reported before seeing the

  # request to report it.

  errormsg "$*" /

           "Please report the installed version of the /"x11-common/"" /

           "package and the complete text of this error message to" /

           "<debian-x@lists.debian.org>."

}

 

# initialize variables for use by all session scripts

 

OPTIONFILE=/etc/X11/Xsession.options

 

SYSRESOURCES=/etc/X11/Xresources

USRRESOURCES=$HOME/.Xresources

 

SYSSESSIONDIR=/etc/X11/Xsession.d

USERXSESSION=$HOME/.xsession

USERXSESSIONRC=$HOME/.xsessionrc

ALTUSERXSESSION=$HOME/.Xsession

ERRFILE=$HOME/.xsession-errors

 

# attempt to create an error file; abort if we cannot

if (umask 077 && touch "$ERRFILE") 2> /dev/null && [ -w "$ERRFILE" ] &&

  [ ! -L "$ERRFILE" ]; then

  chmod 600 "$ERRFILE"

elif ERRFILE=$(tempfile 2> /dev/null); then

  if ! ln -sf "$ERRFILE" "${TMPDIR:=/tmp}/xsession-$USER"; then

    message "warning: unable to symlink /"$TMPDIR/xsession-$USER/" to" /

             "/"$ERRFILE/"; look for session log/errors in" /

             "/"$TMPDIR/xsession-$USER/"."

  fi

else

  errormsg "unable to create X session log/error file; aborting."

fi

# truncate ERRFILE if it is too big to avoid disk usage DoS

if [ "`stat -c%s /"$ERRFILE/"`" -gt 500000 ]; then

  T=`mktemp -p "$HOME"`

  tail -c 500000 "$ERRFILE" > "$T" && mv -f "$T" "$ERRFILE" || rm -f "$T"

fi

 

exec >>"$ERRFILE" 2>&1

echo "$PROGNAME: X session started for $LOGNAME at $(date)"

 

# sanity check; is our session script directory present?

 

#如果/etc/X11/Xsession.d不存在或不是一个目录则打印错误信息并退出。

if [ ! -d "$SYSSESSIONDIR" ]; then

  errormsg "no /"$SYSSESSIONDIR/" directory found; aborting."

fi

# Attempt to create a file of non-zero length in /tmp; a full filesystem can

# cause mysterious X session failures.  We do not use touch, :, or test -w

# because they won't actually create a file with contents.  We also let standard

# error from tempfile and echo go to the error file to aid the user in

# determining what went wrong.

WRITE_TEST=$(tempfile)

if ! echo "*" >>"$WRITE_TEST"; then

  message "warning: unable to write to ${WRITE_TEST%/*}; X session may exit" /

          "with an error"

fi

rm -f "$WRITE_TEST"

# use run-parts to source every file in the session directory; we source

# instead of executing so that the variables and functions defined above

# are available to the scripts, and so that they can pass variables to each

# other

 

#将/etc/X11/Xsession.d目录中的所有文件都读出,并存入SESSIONFILES变量中。

SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)

#如果SESSIONFILES变量中的字符串不为空,即/etc/X11/Xsession.d中有文件存在

if [ -n "$SESSIONFILES" ]; then

  set +e #关闭errexit选项

  for SESSIONFILE in $SESSIONFILES; do

    . $SESSIONFILE #在当前shell环境下执行该文件

  done

  set –e #打卡errexit选项

fi

exit 0

 

从以上的对Xsession脚本文件的分析,可以看出,Xsession脚本仅仅是执行了/etc/X11/Xsession.d目录下的所有文件,在该目录下,文件包括:

20x11-common_process-args

30x11-common_xresources

40x11-common_xsessionrc

50x11-common_determine-startup

55gnome-session_gnomerc

60seahorse

60xdg-user-dirs-update

80im-switch

90-console-kit

90x11-common_ssh-agent

99x11-common_start

 

每个文件名都以数字开头,这主要是为了确保这些脚本的执行顺序,run-parts会将数字小的排在前面,这样就能确保以上文件能按数字由小到大的顺序执行。

 

1、20x11-common_process-args

    这个文件主要是处理传给/etc/X11/xinit/ xinitrc脚本文件的参数的。该参数个数只能为0或一个,否则将不进行任何处理。如果该参数是failsafe,则该脚本将执行x-terminal-emulator,否则就执行该参数。需要说明的是,x-terminal-emulator是一个符号链接,指向/etc/alternatives/x-terminal-emulator,同时,/etc/alternatives/x-terminal-emulator也是一个符号链接,它指向/usr/bin/gnome-terminal.wrapper,而gnome-terminal.wrapper则是一个perl脚本,它最终是调用了gnome-terminal。

 

2、30x11-common_xresources

    该文件主要是调用xrdb来将/etc/X11/Xresources目录下及$HOME/.Xresources目录下的文件的内容来设置根窗口的屏幕 0 上的RESOURCE_MANAGER属性的内容。

 

3、40x11-common_xsessionrc

    该文件主要是判断$HOME/.xsessionrc文件是否存在,如果存在则执行该脚本文件。

 

4、50x11-common_determine-startup

    该文件主要先查看配置文件/etc/X11/Xsession.options中是否允许使用用户的xsession,如果/etc/X11/Xsession.options中存在allow-user-xsession字段,则查看$HOME/.xsession是否存在并有执行权限,如果是,则将STARTUP变量设置为该文件,如果没有执行权限就将STARTUP变量设置为“sh 该xsession文件”。如果此时STARTUP变量仍然为空,则将其设置为x-session-manager,x-window-manager或x-terminal-emulator。注意:这个STARTUP将会在后面的脚本中被启动。

 

5、55gnome-session_gnomerc

   该文件会先得到STARTUP的basename,如:STARTUP=/usr/bin/x-session-manager,则其basename为x-session-manager。再判断该basename 是否为gnome-session,或者为x-session-manager并且x-session-manager是个符号链接,它指向/usr/bin/gnome-session,如果是则执行$HOME/.gnomerc(如果该文件存在并且可读)。

 

6、60seahorse

   将STARTUP重新赋值为“/usr/bin/seahorse-agent $STARTUP”,这个可能只是为安全考虑才这么做的,具体的我也不是很清楚,只是看了一下seahorse-agent的帮助,知道seahorse是一个GNOME的应用程序,它用于为用户的输入进行暂时的安全存储,而seahorse-agent则是seahorse的一个代理而已。

 

7、60xdg-user-dirs-update

   用xdg-user-dirs-update自动生成$HOME下的文件夹,该命令主要是根据/etc/xdg/user-dirs.defaults文件的内容来为用户创建文件夹的。

 

8、80im-switch

   该文件主要用于设置输入法。具体的请自己参考文件内容。

 

9、90-console-kit

   如果环境变量$XDG_SESSION_COOKIE为空,并且/usr/bin/ck-launch-session可执行,则将STARTUP重新赋值为” /usr/bin/ck-launch-session $STARTUP”。至于ck-launch-session的功能,我也不是很清楚,估计是和session有关。

 

10、90x11-common_ssh-agent

   该文件主要先查看配置文件/etc/X11/Xsession.options中是否使用ssh agent,如果/etc/X11/Xsession.options中存在use-ssh-agent字段,则判断/usr/bin/ssh-agent是否可执行,并且环境变量$SSH_AUTH_SOCK和$SSH2_AUTH_SOCK是否都为空,如果是,这将STARTUP重新赋值为” /usr/bin/ssh-agent $STARTUP”。

 

11、99x11-common_start

    它仅仅是用exec启动$STARTUP。关于exec,在Bourne shell中,它与fork的区别就在于它执行一个新的脚本不需创建sub-shell,而它与Source和Dot的区别就在与在这条语句后面的语句将不会再被执行。此时,我们可以发现变量$STARTUP的值为:“startup=/usr/bin/ssh-agent  /usr/bin/ck-launch-session /usr/bin/seahorse-agent --execute x-session-manager”, 因此,最终将会被执行的就是这么一条语句。而x-session-manager在Ubuntu8.04中仅仅是个符号链接,它最终指向的是gnome-session。

    gnome-session则是启动GNOME桌面环境的,这个程序一般被登入管理器gdm、xdm和脚本startx调用。(gnome-session如何启动桌面,待研究)

 


 

4       startx启动过程小结

综上所述,startx的默认启动过程为:startx调用并将系统文件/etc/X11/xinit/xinitrc/etc/X11/xinit/xserverrc 作为参数传给xinitxinit就会先执行系统文件/etc/X11/xinit/xserverrc以启动X Server,然后执行/etc/X11/xinit/xinitrc,而xinitrc则会执行脚本/etc/X11/Xsession,而Xsession则会按顺序调用执行/etc/X11/Xsession.d目录下的文件,从而最终调用了gnome-session这个用于启动GNOME桌面环境的程序

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

startx analyze 的相关文章

  • Tomcat 和 TomEE、TomEE 和 TomEE Plus 之间有什么区别

    我想在服务器中部署 EJB Ear 但我对选择服务器感到非常困惑tomcat TomEE and TomEE Plus 两者有什么区别Tomcat and TomEE 其中有哪些新功能TomEE and TomEE Plus 在什么情况下才
  • Bash 颜色可变输出

    我有一个变量 比方说 x它的值是website com 我希望能够调用该变量并向其应用外壳颜色 如下所示 echo e 033 1 32m x 033 0m 问题不在于颜色 而在于脚本解释输出的方式 所以我得到的输出是 x 我需要输出显然是
  • Magento - 检查管理员和客户是否登录

    我有一个安装了 Magento 1 4 0 1 的 Web 服务器 我有另一个与之共享凭据的网站 我已经设法检查客户是否登录 在更改 Magento 中的 cookie 位置之后 但是当我还尝试确定管理员是否登录时 事情变得复杂 我只能得到
  • 如何在 SSIS 变量中存储“完全限定”和“仅名称”文件名

    我有一个 SSIS 包 其中有一个 Foreach 循环容器 加载静态文件夹中的所有 txt 文件 我将完全限定的文件名作为在连接字符串中使用的变量传递 我现在只需将文件名传递给一个变量以用于执行存储过程 问题是如果我将 Foreach 循
  • Rails 5 和 Devise:如何在不更改默认策略的情况下禁用基于令牌的策略上的会话

    我有一个 Rails 5 应用程序 使用两种身份验证策略 一种使用基于令牌的身份验证 另一种使用基于默认会话的身份验证 当我触发令牌身份验证时 我试图禁用会话保存 因为当我使用 JWT 对用户进行身份验证时 它会保存会话 并且该会话应该是无
  • 是否可以使函数接受给定参数的多种数据类型?

    编写函数时 我必须声明输入和输出数据类型 如下所示 int my function int argument 是否可以声明我的函数接受 int bool 或 char 类型的变量 并且可以输出这些数据类型 non working examp
  • PHP:会话不工作

    当用户在客户端登录时 我将重定向到服务器 一旦验证了他的 user id 和密码 我将在 user id 上设置会话 我将重定向回客户端 然后 我要求填写个人资料信息 如果他想通过 facebook 填写信息 则会出现弹出窗口 请求 fac
  • 如何检查 servlet 中的 sessionId 是否有效 (java)

    我在我的 Web 应用程序中维护 sessionid 和 HttpSession 对象的映射 我使用 HttpSessionListener 从地图中填充或删除会话 当我的网络服务器崩溃 宕机并恢复时 我需要一种方法来检查提交的 sessi
  • SSIS Forloop:根据迭代次数为变量名称赋值

    我正在尝试使用 For 循环容器为最多 10 个不同的变量赋值 变量1 变量2 变量10 基于迭代次数 我需要循环根据一个变量迭代一定次数 该变量已根据查询的结果集分配了一个整数值 该部分工作得很好 我不知道如何告诉 for 循环使用哪个变
  • 使用 google app-engine 跨浏览器/服务器重新启动会话持久性

    如何使会话在浏览器 服务器重新启动后持续存在 我正在使用谷歌应用程序引擎 每次重新启动浏览器和 或服务器时 我都会得到一个新的会话 ID String jSessionId this getThreadLocalRequest getSes
  • NodeJS 快速会话 req.session 未定义

    我正在开发一个简单的登录系统 但会话似乎没有保存 我编写了一个简单的代码进行测试 谁能告诉我它有什么问题吗 我正在运行登录 之后我正在运行 is logged 但我从未登录并且两个会话都未定义 var port process env PO
  • Rails 3 session_store 域 :all 的作用是什么?

    更新了问题以使其更清楚 据我所知 您可以设置 session store 的域以在子域之间共享会话 如下所示 Rails application config session store cookie store key gt my key
  • Symfony2 - 访问被拒绝(用户未经过完全身份验证)

    我正在使用 Symfony2 开发一个网站 直到今天 登录没有问题 但现在登录时我没有正确验证 Symfony 分析器将我列为logged in as anon而不是我登录的用户 我还被重定向回登录页面而不是目标路径 登录过程由传统的登录表
  • 您应该通过属性访问同一类中的变量吗?

    如果您有一个获取和设置实例变量的属性 那么通常您总是使用该类外部的属性来访问它 我的问题是你也应该在课堂上这样做吗 如果有的话 我总是使用该属性 即使是在班级内 但我想听到一些支持和反对的论据 以确定哪个是最正确的以及为什么 或者这只是项目
  • SSIS将字符串变量保存到文本文件

    看起来应该很简单 但到目前为止我还没有找到一种方法将存储在 SSIS 字符串变量中的值保存到文本文件中 我研究过在数据流内部使用平面文件目标 但这需要数据流源 关于如何做到这一点有什么想法吗 使用脚本任务 我刚刚尝试过这个 我创建了一个文件
  • 如何将批处理变量设置为另一个脚本的输出

    我尝试将批处理变量设置为另一个命令的输出 在 Linux Unix 中 您可以简单地使用反引号 例如 在 csh 中 set MY VAR tail etc passwd windows 批处理中有类似的东西吗 实际上我已经发现了一些东西
  • 关于 PHP 范围的问题 - 从 Java 程序员的角度来看

    我对 PHP 还很陌生 所以我试图理解 PHP Web 应用程序中的范围概念 在 Java 世界中 Java Web 应用程序 使用 Java Server Pages JSP 及以上 将允许 Java Bean 具有以下级别的范围 Pag
  • 错误:在 Google 应用引擎上部署节点 js 时找不到模块“/workspace/server.js”

    经过一周的搜索 我无法找到适用于我的 Node js 应用程序的应用程序引擎部署问题的解决方案 我已经用这个替换了原来的代码Express 的 hello world 示例 https expressjs com en starter he
  • 通过PHP从网站上传文件到Amazon EC2服务器

    我有一个网站 bedatify com 我想创建一个页面 人们可以在其中将图像上传到我的亚马逊 EC2 服务器 我检查了类似的问题 例如无法在 Amazon EC2 上上传文件 php https stackoverflow com que
  • 在 Postgres 9.0+ 中使用 PL/pgSQL 循环表

    我想循环遍历所有表以计算每个表中的行数 以下查询给我一个错误 DO DECLARE tables CURSOR FOR SELECT tablename FROM pg tables WHERE tablename NOT LIKE pg

随机推荐

  • 解决 node.js+MySQL 数据库读取Date日期 前端显示时间差8个小时

    问题描述 后端使用 node js Express 框架 连接 mysql 数据库 前端实现数据的编辑修改功能 发现前端发出的更新数据请求正常 数据库中显示的 Date 类型的日期正确 但前端页面上展示的日期少一天 不设定format 直接
  • VTK编译和安装

    准备工作 请先安装好以下工具和下载需要的VTK源码 Virtual Studio CMake Qt 如果需要结合Qt开发 需要安装好Qt VTK源码 以下是本人的环境 VS 2019 CMake 3 20 1 Qt 5 15 2 VTK 8
  • C/C++编程:定时器

    什么是定时器 很多场景都会用到定时器 比如心跳检测 倒计时 技能冷却等 定时器分类 一般定时任务的形式表现为 经过固定时间后触发 按照固定频率周期性触发 在某个时刻触发 定时器的本质 那定时器到底是什么呢 可以理解为这样一个数据结构 存储一
  • ImportError: rocketmq dynamic library not found

    Traceback most recent call last File initialtomq py line 10 in
  • centOS-7静态ip配置

    centOS 7静态ip配置 1 确定网关 vmware虚拟机 gt 编辑菜单 gt 虚拟网络编辑器 gt 打开窗口 gt 选中vmnet8虚拟网卡 gt nat设置 gt 查看网关 具体如下图 2 查看可用的ip网段 vmware虚拟机
  • 06-----the inferior stopped because it triggered an exception

    这个问题总结一下 1 指针非法访问或者数组越界导致的 2 相关的静态库 动态库版本与编译器的位数不一致导致的 而我就是第2个问题导致的 因为我出错的地方是一个int型的变量 并非指针 故将QT的MSCV编译位数改成32位后 程序正常 因为我
  • 快手did did_gt edid的注册过程

    接口 https gdfp ksapisrv com rest infra gdfp report kuaishou android did 是本地生成的16进制 或者 获取的 android id did gt 是did生成时间戳 159
  • wx小程序结构目录介绍及创建和删除

    仔细查看之前创建的项目 可以发现项目里生成很多不同类型的文件 json 后缀 JSON 配置文件 wxml 后缀 WXML 模板文件 wxss 后缀 WXSS 样式文件 js 后缀 JS 脚本逻辑文件 1 sitemap json小程序收录
  • 人机交互的困难之一常常在于没有形成有效的你、我、他之间的互换。

    人机交互的困难之一常常在于没有形成有效的你 我 他之间的互换 而要形成交互过程中有效的你 我 他角色的互换 可以考虑以下几个方面 清晰定义角色 在交互开始之前 明确定义每个参与者的角色和身份 机器可以被定义为 你 而用户则为 我 这样可以建
  • 《Cesium 进阶知识点》 - 加载天地图三维地名服务(无Cesium 版本依赖)

    一 解决依赖 天地图官网说只支持 1 52 1 58 1 63 1 这 3个版本 其它版本报错 但我只使用三维地名服务 所以做了如下修改 我在 1 80 版 和 1 84 版中测试有效 操作部署是 1 根据官网安装 cesium tdt 插
  • Python------- if-else语句介绍

    Python的if else语句是一个判断性语句 要判断就需要有条件以及满足条件和不满足条件的情况 以下就此进行说明 1 if else的使用格式 if 条件 满足条件所要做的事情 else 不满足条件所要做的事情 这里需要注意的是 if和
  • 数据库SQL性能优化之详解

    一 问题的提出 在应用系统开发初期 由于开发数据库数据比较少 对于查询SQL语句 复杂视图的的编写等体会不出SQL语句各种写法的性能优劣 但是如果将应用系统提交实际应用后 随着数据库中数据的增加 系统的响应速度就成为目前系统需要解决的最主要
  • c语言 (3×3)矩阵转置

    题目描述 写一个函数 使给定的一个二维数组 转置 即行列互换 输入 一个3x3的矩阵 输出 转置后的矩阵 样例输入 1 2 3 4 5 6 7 8 9 样例输出 1 4 7 2 5 8 3 6 9 废话不说还是直接上代码 include
  • 使用STM32CUBEIDE创建工程,点亮LED

    1 创建LED驱动文件 先在工程下新建一个文件夹命名为icode存放驱动程序 然后对每一个外设新建新的驱动文件夹 如驱动LED就新建文件夹led 然后在led文件夹下创建对应的头文件和源文件 即led h和led c 然后编写对应外设的驱动
  • X.509证书的使用

    总结一下如何使用X 509证书来保护我们的设备的数据传输 证书的签发 以下是证书签发的流程 为了更好的演示 我们需要分别创建两个根证书 并且用每个根证书来颁发一个客户端证书 这两个根证书分别为root 1 crt以及root 2 crt 对
  • Java上传下载ftp文件

    在Java中连接FTP服务器可以使用Apache Commons Net库提供的FTPClient类 以下是一个简单的示例代码 演示如何连接到FTP服务器 进行文件上传和下载操作 import org apache commons net
  • 【Windows上同时安装两个不同版本MYSQL】MySQL安装教程--5.7和8.0版本

    一 MySQL官网下载对应版本的zip文件 最新版本8 0 34下载链接 https dev mysql com downloads mysql MySQL 5 7下载链接 https downloads mysql com archive
  • vue中使用百度地图自定义信息窗口

    场景 点击地图上的标注的时候 希望可以显示自定义的信息弹窗 具体效果如下 注意 如果只是简单显示信息 则使用InfoWindow信息窗口或者标注本身的title属性即可 想自定义就使用infoBox自定义信息窗口工具 效果 效果图是GIF图
  • 【满分】【华为OD机试真题2023B卷 JS】矩阵最大值

    华为OD2023 B卷 机试题库全覆盖 刷题指南点这里 矩阵最大值 知识点矩阵数组 时间限制 1s 空间限制 32MB 限定语言 不限 题目描述 给定一个仅包含0和1的N N二维矩阵 请计算二维矩阵的最大值 计算规则如下 1 每行元素按下标
  • startx analyze

    1 xinit 在说明startx之前 我想我们应该先了解一下xinit 因为startx就是通过调用xinit启动X的 1 1 功能 当我们安装了Ubuntu后 默认就已经安装了xinit 它位于 usr bin下 xinit是一个二进制