( exec sh -i 3<<SCRIPT 4<&0 <&3 ⏎
echo "do this thing"
echo "do that thing"
exec 3>&- <&4
SCRIPT
)
Questo è meglio se lo script viene eseguito con exec $0.O se uno di quei descrittori di file indirizza a un dispositivo terminale che non è attualmente utilizzato, sarà di aiuto: devi ricordare che anche altri processi vogliono controllare quel terminale.
E a proposito, se il tuo obiettivo è, come presumo sia, preservare l'ambiente dello script dopo averlo eseguito, probabilmente saresti molto meglio servito con:
. ./script
Della shell .dote bash's sourcenon sono la stessa cosa - della shell .dotè POSIX specificato come uno speciale comando incorporato della shell ed è quindi il più vicino ad essere garantito come si può ottenere, anche se questo non è affatto una garanzia che ci sarà ...
Sebbene quanto sopra dovrebbe fare come ti aspetti con un piccolo problema. Ad esempio, puoi:
( exec sh -i 3<<SCRIPT 4<&0 <&3 ⏎
echo "do this thing"
echo "do that thing"
$(cat /path/to/script)
exec 3>&- <&4
SCRIPT
)
La shell eseguirà il tuo script e ti riporterà al prompt interattivo - a patto che tu eviti di utilizzare exitla shell dal tuo script, ovvero, o in background il tuo processo - che collegherà il tuo I / O a/dev/null.
DEMO:
% printf 'echo "%s"\n' "These lines will print out as echo" \
"statements run from my interactive shell." \
"This will occur before I'm given the prompt." >|/tmp/script
% ( exec sh -i 3<<SCRIPT 4<&0 <&3
echo "do this thing"
echo "do that thing"
$(cat /tmp/script)
exec 3>&- <&4
SCRIPT
)
sh-4.3$ echo "do this thing"
do this thing
sh-4.3$ echo "do that thing"
do that thing
sh-4.3$ echo "These lines will print out as echo"
These lines will print out as echo
sh-4.3$ echo "statements run from my interactive shell."
statements run from my interactive shell.
sh-4.3$ echo "This will occur before I'm given the prompt."
This will occur before I'm given the prompt.
sh-4.3$ exec 3>&- <&4
sh-4.3$
MOLTI JOBS
Ritengo che dovresti familiarizzare con le opzioni integrate di gestione delle attività della shell. @Kiwy e @jillagre hanno già toccato questo aspetto nelle loro risposte, ma potrebbe giustificare ulteriori dettagli. E ho già detto una conchiglia speciale POSIX specificato built-in, ma set, jobs, fg,e bgsono un po 'di più, e, come un'altra risposta dimostra trape killsono due altri ancora.
Se non stai già ricevendo notifiche istantanee sullo stato di processi in background in esecuzione contemporaneamente, è perché le tue opzioni di shell correnti sono impostate sul valore predefinito specificato da POSIX di -m, ma puoi invece ottenere queste in modo asincrono con set -b:
% man set
−b This option shall be supported if the implementation supports the
User Portability Utilities option. It shall cause the shell to
notify the user asynchronously of background job completions. The
following message is written to standard error:
"[%d]%c %s%s\n", <job-number>, <current>, <status>, <job-name>
where the fields shall be as follows:
<current> The character '+' identifies the job that would be
used as a default for the fg or bg utilities; this
job can also be specified using the job_id "%+" or
"%%". The character '−' identifies the job that
would become the default if the current default job
were to exit; this job can also be specified using
the job_id "%−". For other jobs, this field is a
<space>. At most one job can be identified with '+'
and at most one job can be identified with '−'. If
there is any suspended job, then the current job
shall be a suspended job. If there are at least two
suspended jobs, then the previous job also shall be a
−m This option shall be supported if the implementation supports the
User Portability Utilities option. All jobs shall be run in their
own process groups. Immediately before the shell issues a prompt
after completion of the background job, a message reporting the
exit status of the background job shall be written to standard
error. If a foreground job stops, the shell shall write a message
to standard error to that effect, formatted as described by the
jobs utility. In addition, if a job changes status other than
exiting (for example, if it stops for input or output or is
stopped by a SIGSTOP signal), the shell shall write a similar
message immediately prior to writing the next prompt. This option
is enabled by default for interactive shells.
Una caratteristica fondamentale dei sistemi basati su Unix è il loro metodo di gestione dei processi signals. Una volta ho letto un articolo illuminante sull'argomento che paragona questo processo alla descrizione del pianeta di Douglas Adams NowWhat:
"In The Hitchhiker's Guide to the Galaxy, Douglas Adams menziona un pianeta estremamente noioso, abitato da un gruppo di umani depressi e una certa razza di animali con denti aguzzi che comunicano con gli umani mordendoli molto duramente nelle cosce. Questo è sorprendentemente simile a UNIX, in cui il kernel comunica con i processi inviando loro segnali paralizzanti o mortali. I processi possono intercettare alcuni segnali e provare ad adattarsi alla situazione, ma la maggior parte di loro no. "
Questo si riferisce a kill signals.
% kill -l
> HUP INT QUIT ILL TRAP ABRT BUS FPE KILL USR1 SEGV USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH POLL PWR SYS
Almeno per me, la citazione sopra ha risposto a molte domande. Ad esempio, avevo sempre considerato molto strano e per nulla intuitivo che se avessi voluto monitorare un ddprocesso, dovevo killfarlo. Dopo aver letto che aveva senso.
Direi che la maggior parte di loro non cerca di adattarsi per una buona ragione - può essere un fastidio molto maggiore di quanto sarebbe un vantaggio avere un sacco di processi che inviano spam al tuo terminale con qualsiasi informazione che i loro sviluppatori pensassero potesse essere importante per te .
A seconda della configurazione del terminale (che è possibile verificare stty -a) , CTRL+Zè probabile che venga inoltrato a un SIGTSTPleader del gruppo di processi in primo piano corrente, che è probabilmente la shell, e che dovrebbe anche essere configurato per impostazione predefinita a trapquel segnale e sospendere l'ultimo comando. Ancora una volta, come mostrano le risposte di @jillagre e @Kiwy insieme, non c'è modo di impedirti di adattare questa funzionalità al tuo scopo come preferisci.
SCREEN JOBS
Pertanto, per trarre vantaggio da queste funzionalità, è necessario prima comprenderle e personalizzarne la gestione in base alle proprie esigenze. Ad esempio, ho appena trovato questo screenrc su Github che include combinazioni discreen tasti per SIGTSTP:
# hitting 'C-z C-z' will run Ctrl+Z (SIGTSTP, suspend as usual)
bind ^Z stuff ^Z
# hitting 'C-z z' will suspend the screen client
bind z suspend
Ciò renderebbe semplice sospendere un processo in esecuzione come screenprocesso figlio o il screenprocesso figlio stesso come desiderato.
E subito dopo:
% fg
O:
% bg
In primo piano o in background il processo come preferisci. Il jobsbuilt-in può fornirti un elenco di questi in qualsiasi momento. L'aggiunta -ldell'operando includerà i dettagli pid.