1 | #!/bin/bash |
2 | |
3 | THIS=$0 |
4 | ARGS=$@ |
5 | name=$(basename $THIS) |
6 | |
7 | usage () { |
8 | cat <<EOF |
9 | Usage: $name: redirect input/output/error of a running process |
10 | Two ways to run this program: |
11 | $name [-q][-o <outfile>] [-e <errorfile>] [-i <inputfile>] [-n <fd>:<filename> ] <pid> |
12 | or simply: |
13 | $name [-q] <pid> |
14 | The first form files specified in -o, -e, and -i options will become |
15 | standard output, standard error, and standard input. At least one |
16 | option must be specified, or second form will be assumed. |
17 | For example, using Bash syntax: |
18 | bash -c 'sleep 1m && echo "rise and shine"' & |
19 | $name -o /tmp/test \$! |
20 | The same with explicit stdout descriptor number (1) using -n option: |
21 | bash -c 'sleep 1m && echo "rise and shine"' & |
22 | $name -n 0:/tmp/test \$! |
23 | |
24 | In the second form, current in/out/err are remapped into the process. |
25 | For example, using Bash syntax: |
26 | bash -c 'sleep 1m && echo "rise and shine"' & |
27 | $name \$! >>/tmp/test |
28 | These examples should be equivalent (i.e. -o foo will append to file foo, |
29 | if it already exists) with respect to stdout, but in the second stdin and |
30 | stderr are remapped as well. |
31 | |
32 | Option (-n) allows explicit specification of file descriptors. |
33 | It can be given multiple times, e.g.: |
34 | $name -n 0:/tmp/stdin -n 1:/tmp/stdout -n 2:/tmp/stderr PID |
35 | is equivalent to, using Bash syntax: |
36 | $name PID </tmp/stdin >/tmp/stdout 2>/tmp/stderr |
37 | All files specified in (-n) option are opened in read/write & append mode. |
38 | |
39 | Summary of options: |
40 | -i <stdin> specify filename of the new standard input |
41 | -o <stdout> specify filename of the new standard output |
42 | -e <stderr> specify filename of the new standard error |
43 | -n <fd>:<filename> specify descriptor number and filename to remap to |
44 | -q be quiet |
45 | -h this help |
46 | |
47 | EOF |
48 | } |
49 | |
50 | |
51 | warn () { |
52 | echo "$name: $@" >&2 |
53 | } |
54 | |
55 | # XXX add multiple -n option |
56 | quiet="no" |
57 | nopt="" |
58 | while getopts "ho:e:i:qn:" opt; do |
59 | case $opt in |
60 | ( o ) stdout=$OPTARG; ;; |
61 | ( e ) stderr=$OPTARG; ;; |
62 | ( i ) stdin=$OPTARG; ;; |
63 | ( n ) nopt="$nopt $OPTARG"; ;; |
64 | ( q ) quiet="yes"; ;; |
65 | ( * ) usage; exit 0; ;; |
66 | esac |
67 | done |
68 | |
69 | shift $((OPTIND-1)) |
70 | |
71 | |
72 | if [ $# != 1 ]; then |
73 | usage |
74 | exit 1 |
75 | fi |
76 | |
77 | if [ -n "$stdout" ] && ! 2>/dev/null : >> $stdout ; then |
78 | warn "Cannot write to (-o) $stdout" |
79 | exit 1 |
80 | fi |
81 | |
82 | if [ -n "$stderr" ] && ! 2>/dev/null : >> $stderr ; then |
83 | warn "Cannot write to (-e) $stderr" |
84 | exit 1 |
85 | fi |
86 | |
87 | if [ -n "$stdin" ] && ! 2>/dev/null : >> $stdin ; then |
88 | warn "Cannot write to (-i) $stdin" |
89 | exit 1 |
90 | fi |
91 | |
92 | fds="" |
93 | if [ -n "$nopt" ]; then |
94 | for n_f in $nopt; do |
95 | n=${n_f%%:*} |
96 | f=${n_f##*:} |
97 | if [ -n "${n//[0-9]/}" ] || [ -z "$f" ]; then |
98 | warn "Error parsing descriptor (-n $n_f)" |
99 | exit 1 |
100 | fi |
101 | if ! 2>/dev/null : >> $f; then |
102 | warn "Cannot write to (-n $n_f) $f" |
103 | exit 1 |
104 | fi |
105 | fds="$fds $n" |
106 | fns[$n]=$f |
107 | done |
108 | fi |
109 | if [ -z "$stdout" ] && [ -z "$stderr" ] && [ -z "$stdin" ] && [ -z "$nopt" ]; then |
110 | #second invocation form: dup to my own in/err/out |
111 | [ -e /proc/$$/fd/0 ] && stdin=$(readlink /proc/$$/fd/0) |
112 | [ -e /proc/$$/fd/1 ] && stdout=$(readlink /proc/$$/fd/1) |
113 | [ -e /proc/$$/fd/2 ] && stderr=$(readlink /proc/$$/fd/2) |
114 | if [ -z "$stdout" ] && [ -z "$stderr" ] && [ -z "$stdin" ]; then |
115 | warn "Could not determine current standard in/out/err" |
116 | exit 1 |
117 | fi |
118 | fi |
119 | |
120 | PID=$1 |
121 | if ! 2>/dev/null kill -0 $PID; then |
122 | warn "Error accessing PID $PID" |
123 | exit 1 |
124 | fi |
125 | |
126 | if [ "$quiet" != "yes" ]; then |
127 | msg_stdout="Remaining standard output of $PID is redirected to $stdout\n" |
128 | msg_stderr="Remaining standard error of $PID is redircted to $stderr\n" |
129 | fi |
130 | |
131 | gdb_cmds () { |
132 | local _name=$1 |
133 | local _mode=$2 |
134 | local _desc=$3 |
135 | local _msgs=$4 |
136 | local _len |
137 | |
138 | [ -w "/proc/$PID/fd/$_desc" ] || _msgs="" |
139 | if [ -d "/proc/$PID/fd" ] && ! [ -e "/proc/$PID/fd/$_desc" ]; then |
140 | warn "Attempting to remap non-existent fd $n of PID ($PID)" |
141 | fi |
142 | |
143 | [ -z "$_name" ] && return |
144 | |
145 | echo "set \$fd=open(\"$_name\", $_mode)" |
146 | echo "set \$xd=dup($_desc)" |
147 | echo "call dup2(\$fd, $_desc)" |
148 | echo "call close(\$fd)" |
149 | if [ $((_mode & 3)) ] && [ -n "$_msgs" ]; then |
150 | _len=$(echo -en "$_msgs" | wc -c) |
151 | echo "call write(\$xd, \"$_msgs\", $_len)" |
152 | fi |
153 | echo "call close(\$xd)" |
154 | } |
155 | |
156 | trap '/bin/rm -f $GDBCMD' EXIT |
157 | GDBCMD=$(mktemp /tmp/gdbcmd.XXXX) |
158 | { |
159 | #Linux file flags (from /usr/include/bits/fcntl.sh) |
160 | O_RDONLY=00 |
161 | O_WRONLY=01 |
162 | O_RDWR=02 |
163 | O_CREAT=0100 |
164 | O_APPEND=02000 |
165 | echo "#gdb script generated by running '$0 $ARGS'" |
166 | echo "attach $PID" |
167 | gdb_cmds "$stdin" $((O_RDONLY)) 0 "$msg_stdin" |
168 | gdb_cmds "$stdout" $((O_WRONLY|O_CREAT|O_APPEND)) 1 "$msg_stdout" |
169 | gdb_cmds "$stderr" $((O_WRONLY|O_CREAT|O_APPEND)) 2 "$msg_stderr" |
170 | for n in $fds; do |
171 | msg="Descriptor $n of $PID is remapped to ${fns[$n]}\n" |
172 | gdb_cmds ${fns[$n]} $((O_RDWR|O_CREAT|O_APPEND)) $n "$msg" |
173 | done |
174 | #echo "quit" |
175 | } > $GDBCMD |
176 | |
177 | cat $GDBCMD |
178 | echo |
179 | if gdb -batch -n -x $GDBCMD >/dev/null </dev/null; then |
180 | [ "$quiet" != "yes" ] && echo "Success" >&2 |
181 | else |
182 | warn "Remapping failed" |
183 | fi |
184 | #cp $GDBCMD /tmp/gdbcmd |
185 | rm -f $GDBCMD |
Travelled to 2 computer(s): bhatertpkbcr, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033366 |
Snippet name: | dupx |
Eternal ID of this version: | #1033366/2 |
Text MD5: | 65ac9705493e4d2ccbefa5218d8a645a |
Author: | stefan |
Category: | |
Type: | Document |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2021-10-25 05:48:55 |
Source code size: | 5281 bytes / 185 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 150 / 56 |
Version history: | 1 change(s) |
Referenced in: | [show references] |