GNU Screen terminal line settings - gnu-screen

I want to use GNU screen to monitor to a serial USB port like this:
$ screen /dev/ttyUSB0 115200
But I need to tweak a few terminal line settings. I have made several attempts but none seem to work. For example, to send NL+CR for a newline character, not just NL, the terminal line setting is onlcr.
Attempt 1 - without any special settings:
$ screen /dev/ttyUSB0 115200
# only sends NL
Attempt 2 - via screen:
$ screen /dev/ttyUSB0 115200,onlcr
# still only sends NL
Attempt 3 - via ssty:
$ stty -F /dev/ttyUSB0 onlcr
$ screen /dev/ttyUSB0 115200
# still only sends NL
Attempt 4 - via both:
$ stty -F /dev/ttyUSB0 onlcr
$ screen /dev/ttyUSB0 115200,onlcr
# still only sends NL
Attempt 5 - in the other order:
$ screen /dev/ttyUSB0 115200,onlcr
# then ctrl+a, ctrl+z to pause the screen session
$ stty -F /dev/ttyUSB0 onlcr
stty: /dev/ttyUSB0: Device or resource busy
In all cases, if I run stty to check the terminal line settings I get this:
Before running screen - note the -onlcr is present:
$ stty -F /dev/ttyUSB0
speed 115200 baud; line = 0;
kill = ^H; min = 100; time = 2;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -echo
Changing the stty setting - note the -onlcr has gone:
$ stty -F /dev/ttyUSB0 onlcr
$ stty -F /dev/ttyUSB0
speed 115200 baud; line = 0;
kill = ^H; min = 100; time = 2;
-icrnl -imaxbel
-opost
-isig -icanon -echo
After running screen - note the -onlcr is back again:
$ stty -F /dev/ttyUSB0
speed 115200 baud; line = 0;
kill = ^H; min = 100; time = 2;
-icrnl -imaxbel
-opost -onlcr
-isig -icanon -echo
It's as if screen ignores any stty settings and resets them to it's own defaults. And this the same on both machines I tested it on; Debain 8.7 and macOS Sierra 10.12.4
I have seen posts with other people facing similar problems but none give a definitive answer. Many people end up recommending an alternative to screen like minicom but now I'm interested.
Can stty settings, like onlcr, be used with screen?

I just went through much the same process, only to find out the screen clobbers the stty settings no matter what. One comment here suggests changing the screen source code:
How to toggle CR/LF in gnu screen?
In the end, I was very happy to find a more minimal dumb-terminal program that allows passing stty-style arguments on the command line:
https://github.com/npat-efault/picocom
It also pretty-prints the serial port settings when it starts so you can easily check them.
Packages exist in Debian-derived distros (sudo apt-get install picocom), and for others it seems that compilation is straightforward. One dependency is the linenoise library, which can be disabled.

The way I handled this is to start screen running without any special terminal options using in your case: screen /dev/ttyUSB0 115200, and then leave it running, and switch over to another terminal window and do the stty commands from there.
If you stop screen, I think it locks the device somehow (or else its because you aren't using sudo). Once in the other window you can type the sudo stty -F /dev/ttyUSB0 onlcr and that will change the behavior of the screen session from then on. The problem is that screen is ignoring the setting passed to it and just configuring the tty its own way. You can type sudo stty -F /dev/ttyUSB0 -a to list the settings from another window while screen is running and then alter them as needed. (Note that on the Mac, the -F should be lower case.)
If you only have the one terminal window then it is problematic because putting screen in the background and leaving it running just mixes input and output streams between the shell and screen process.

Another thing you can do if you have two terminal windows open is a low-level fallback hack when nothing is working: In one terminal type cat /dev/ttyUSB0. Then in the other set up the terminal options you want with sudo stty. Then from this same terminal you can send commands via echo "Some text" > /dev/ttyUSB0. You can translate the output of the cat command by piping it through sed or tr. For example cat /dev/ttyUSB0 | tr '\r' '\n' will translate any received carriage returns to line feeds.

Related

how to create a GNU screen session with multi windows in it?

I alway work in a screen session with some windows, one for shell, one for mysql, one for music player, one for irc, and so on...
The problem is, when you create a screen session, it only creates one window by default. So I have to do Ctrl-a c then issue commands, again and again.
So I wrote a bash function to do this.
d(){
local i=workspace
screen -qls $i
if [ "$?" -ne 11 ];then
screen -dmS $i
screen -S $i -X screen mysql -uroot -p
screen -S $i -X screen irssi
screen -S $i -X screen nvlc $music -Z
screen -r $i -p0
else
screen -r $i
fi
}
My question is, is there a way to start a new screen session with some windows? By this question, I mean new session, NOT for existing sessions using '-X'. And, screen built-in feature, I mean, no shell scripting involved.
I didn't consider .screenrc file at first, because commands in it will be invoked every time you call screen, but sometimes I need to create a new screen session with different things.
One thing I forgot is that, I can choose configuration file.
So I think answer is:
d(){
screen -d -R -S workspace -c ~/.workspace
}
and content of ~/.workspace should be:
screen
screen mysql -uroot -p
screen irssi
screen nvlc
select 0

Can't activate a USB HID Device on BeagleBoneBlack

Background:
I'm trying to figure out how to use ConfigFS to set up an HID device on BeagleBoneBlack.
I found the following example (www.isticktoit.net/?p=1383) on the web and tried it. The sample runs on a Raspberry Pi Zero. However, the sample does not work on my BBB. The following is the script that I wrote and which is executed as root. The script attempts to define a keyboard hid device.
#!/bin/bash
cd /sys/kernel/config/usb_gadget/
modprobe libcomposite
modprobe usb_f_hid
mkdir -p isticktoit
cd isticktoit
echo 0x1d6b > idVendor # Linux Foundation
echo 0x0104 > idProduct # Multifunction Composite Gadget
echo 0x0100 > bcdDevice # v1.0.0
echo 0x0200 > bcdUSB # USB2
mkdir -p strings/0x409
echo "fedcba9876543210" > strings/0x409/serialnumber
echo "Tobias Girstmair" > strings/0x409/manufacturer
echo "iSticktoit.net USB Device" > strings/0x409/product
mkdir -p configs/c.1/strings/0x409
echo "Config 1: ECM network" > configs/c.1/strings/0x409/configuration
echo 250 > configs/c.1/MaxPower
# Add functions here
pwd
mkdir -p functions/hid.xyz
echo 1 > functions/hid.xyz/protocol
echo 1 > functions/hid.xyz/subclass
echo 8 > functions/hid.xyz/report_length
echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.xyz/report_desc
ln -s functions/hid.xyz configs/c.1/
# End functions
ls /sys/class/udc > UDC
The error that I get is "ls: write error: Devicew or resource busy".
I am running Debian Jessie - Linux version 4.4.9-ti-r25
I did an lsmod and libcomposite and usb_f_hid are loaded.
The usb device controller, musb-hdrc-0.auto, is loaded.
Questions:
How can I tell which device is busy?
Where can I find the USB configfs defect bug list for BBB.
Is there a logging file and enabling parameter that would give me a clue as to what is happening?
Thanks for any help
David Glaser
The problem you are likely having with the beaglebone black is the cdc_acm driver. It is difficult to remove (well, not really now that I KNOW how to do it) if you don't know how because the steps aren't just laid out to find anywhere yet. I found this: https://media.defcon.org/DEF%20CON%2023/DEF%20CON%2023%20presentations/DEFCON-23-Phil-Polstra-One-device-to-Pwn-them-all.pdf
which led me to the following solution
#!/usr/bin/env bash
function checkModule(){
MODULE="$1"
if lsmod | grep "$MODULE" &> /dev/null ; then
echo "$MODULE" found.
return 0
else
echo "$MODULE" not found.
return 1
fi
}
if which 'systemctl' | grep "systemctl" &> /dev/null ; then
systemctl stop serial-getty#ttyGS0.service >/dev/null
fi
if checkModule "g_serial" == 0; then
modprobe -r g_serial
fi
if checkModule "usb_f_acm" == 0; then
modprobe -r usb_f_acm
fi
if ! checkModule "libcomposite" == 0; then
modprobe libcomposite
fi
basically, it stops the serial-getty service which allows you to remove the g_serial device and then this allows you to remove usb_f_acm. This in turn removes the libcomposite device, which you actually want to keep. Once this is done, you can likely do all the things you needed to do. I got a nice HID keyboard working this way (well, okay I guess its a KeygleBone Black now)... It is pretty dirt simple once you understand ALL of the pieces, but I'm having a little trouble tearing my device back down. I might not need to eventually, but I'd like to be able to do that and it seems that certain directories cannot be removed (namely the "strings" directories that I've created). This means I can't really fully tear down the device, but maybe I only need to:
echo "" > /sys/kernel/config/usb_gadget/my_gadget/UDC
to actually tear it down. I haven't worked that part out yet. There are also some C libraries, but I've got a bunch of python scripts that I want to use and I don't yet have python wrappers for those. But that probably isn't too much work.
I didn't want to forget to mention, that I tried to throw the above script into rc.local so the beaglebone black I am using would be "HID ready" on boot. There are probably better locations and methods to do this, but I just wanted to use rc.local because the above is a script, rc.local is a script, it should run on boot... But it doesn't... You have to make sure to make rc.local runable ( chmod 755 /etc/rc.local ) as well as modifying the default shell it wants to run (well, it always runs bash, but its method for running bash is the "POSIX" method, and that doesn't seem to work, so you have to force it to run bash in non-POSIX mode with:
#!/usr/bin/bash
Again, there are probably other better methods (I was lazy here and, well, I'm just old school), especially if your device is going to be an IoT device or anything linked to the net, so you might want to consider something else if you need this script to run on boot.
I did stupidly leave out one thing: I made sure the beaglebone black doesn't present its usual "disk" portion as well. I would put the details here, but frankly, those I'd have to track back down. I basically googled around for how to disable the beaglebone black disk. It isn't hard and amounted to me moving some file to another name so it doesn't find the "USB disk" configuration on boot. You can also change a line in the uboot config somewhere I believe, but I didn't really want to do that.
Found the file: /var/local/bb_usb_mass_storage.img
Well, it might be bbg_usb_mass_storage.img if it is a beaglebone green, but I just moved this file so it wouldn't present the mass storage device. That should allow you to do what you want.

Is there a workaround for: "dtrace cannot control executables signed with restricted entitlements"?

It looks like in OS X 10.11 El Capitan, dtruss and dtrace can no longer do what they're meant to do. This is the error I get when I try to run sudo dtruss curl ...:
dtrace: failed to execute curl: dtrace cannot control executables signed with restricted entitlements
I've come across people noticing this problem but so far no solutions.
Is there a way to fix this or work around this?
Following up to Alexander Ushakov and Charles' answers:
Once you csrutil enable --without dtrace, there is an alternative to copying the binary: run the binary in one Terminal window and trace the Terminal process itself in another Terminal window.
In the first terminal window, find its PID:
$ echo $$
1154
In the second terminal window, begin the trace:
$ sudo dtruss -p 1154 -f
Back, in the first terminal window, run the process you want to trace:
$ ls
At this point, you should see the trace in the second window. Ignore the entries for the PID you are tracing (e.g., 1154), and the rest are for the process (and its descendants) you are interested in.
1154/0x1499: sigprocmask(0x3, 0x7FFF53E5C608, 0x0) = 0x0 0
1154/0x1499: sigprocmask(0x1, 0x7FFF53E5C614, 0x7FFF53E5C610) = 0x0 0
3100/0xa9f3: getpid(0x7FFF82A35344, 0x7FFF82A35334, 0x2000) = 3100 0
3100/0xa9f3: sigprocmask(0x3, 0x10BE32EF8, 0x0) = 0x0 0
For those who want to dtrace system shipped binary after csrutil disable, copyit to a directory that is not "restricted", for example, /tmp
CC#~ $ csrutil status
System Integrity Protection status: disabled.
CC#~ $ cp /bin/echo /tmp
CC#~ $ sudo dtruss /tmp/echo
SYSCALL(args) = return
thread_selfid(0x0, 0x0, 0x0) = 46811 0
csops(0x0, 0x0, 0x7FFF51B6CA20) = 0 0
issetugid(0x0, 0x0, 0x7FFF51B6CA20) = 0 0
shared_region_check_np(0x7FFF51B6A918, 0x0, 0x7FFF51B6CA20) = 0 0
stat64("/usr/lib/dtrace/libdtrace_dyld.dylib\0", 0x7FFF51B6BEA8, 0x7FFF51B6CA20 = 0 0
See #J.J's comment: https://apple.stackexchange.com/questions/208762/now-that-el-capitan-is-rootless-is-there-any-way-to-get-dtrace-working/224731#224731
As Andrew notices it's because of System Integrity Protection, also known as "rootless".
You can disable it completely or partially (enable just dtrace with some limitations).
Completely disable SIP
Although not recommended by Apple, you can entirely disable System
Integrity Protection on you Mac. Here's how:
Boot your Mac into Recovery Mode: reboot it and hold cmd+R until a progress bar appears.
Go to Utilities menu. Choose Terminal there.
Enter this command to disable System Integrity Protection:
$ csrutil disable
It will ask you to reboot — do so and you're free from SIP!
Partially disable SIP
Fortunately, SIP is not monolithic: it's built from many different
modules we can disable/enable separately.
Repeat steps 1 and 2 from «Completely disable SIP» section above. Now
in Terminal enter these commands:
$ csrutil clear # restore the default configuration first
$ csrutil enable --without dtrace # disable dtrace restrictions *only*
Reboot and enjoy your OS again.
Dtrace starts to work but you're still unable to attach dtrace to restricted processes
I would post this as a comment but I'm not allowed.
Disabling SIP is not necessary. Just copy the binary to an alternate location and it works just fine:
$ sudo dtruss ping google.com
dtrace: system integrity protection is on, some features will not be available
dtrace: failed to execute ping: dtrace cannot control executables signed with restricted entitlements
$ sudo cp $(which ping) .
$ sudo dtruss ./ping google.com
dtrace: system integrity protection is on, some features will not be available
SYSCALL(args) = return
PING google.com (172.217.10.78): 56 data bytes
^C
$ csrutil status
System Integrity Protection status: enabled.
For binaries that can still function normally after being copied, this is the best option as it captures the entire lifetime of the process and doesn't require disabling any protections.
Looks like completely disabling SIP still blocks dtruss for restricted processes:
$ /usr/bin/csrutil status
System Integrity Protection status: disabled.
$ sudo dtruss /bin/echo "blah"
dtrace: failed to execute /bin/echo: dtrace cannot control executables signed with restricted entitlements
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.11.2
BuildVersion: 15C50
See my answer on related question "How can get dtrace to run the traced command with non-root priviledges?" [sic].
DTrace can snoop processes that are already running. So, start a background process which waits 1sec for DTrace to start up (sorry for race condition), and snoop the PID of that process.
sudo true && \
(sleep 1; ps) & \
sudo dtrace -n 'syscall:::entry /pid == $1/ {#[probefunc] = count();}' $! \
&& kill $!
Full explanation in linked answer.

how do you script gnu screen from within a screen session to open new windows and run commands in them?

From within a screen session, I'd like to run a shell script that opens
a few new screen windows in the same session and start running some
programs in them.
I need a script like this:
screen -t newWindow
[switch to newWindow and execute a command]
screen -t newWindow2
[switch to newWindow2 and execute a command]
I don't know how to accomplish the effect I describe in the brackets.
Any clues? Please note that this is not a script I'll be running to start a screen session. I need this script to be runnable within an existing screen session, in order to add new windows to the session.
Note: you can't launch script working following way from a screen session. And it will open in session no tabs... Its more a related tip than a real answer to the question.
There is an other solution, if you accept to have a screen session by running process...
new session script
#!/bin/sh
echo "nouvelle session screen ${sessionName}"
screen -S ${sessionName} init.sh
echo "screen session: done"
echo "go to ${AnyWhere}"
sleep 1
screenexec ${sessionName} "cd ${AnyWhere}"
init script (here "init.sh")
#!/bin/zsh
zsh -c "sleep 0.2"
screen -d #detach the initialised screen
zsh #let a prompt running
injection script (here screenexec)
#!/bin/sh
# $1 -> nom de screen cible $2 -> commande
echo "injection de «${2}» dans la session «${1}» ..."
screen -x "$1" -X stuff "$2" #inject the command
screen -x "$1" -X eval "stuff \015" #inject \n
echo "Done"
By using this way, you should inject code easily in your screens, interesting if your script act like a deamon...
For those who prefer script in python, I've made a small lib to create sessions, close sessions, inject commands: ScreenUtils.py
It's a small project, which don't handle multiwindows screen sessions.
Forgot to mention I made a real python library out of it long ago: https://github.com/Christophe31/screenutils
Running this script inside screen does what I think you want:
#!/bin/bash
screen vi
screen top

Automatically (or more easily) reconnect to a screen session after network interruption

ADDED: This question is now, I believe, subsumed by this one:
Using GNU Screen completely transparently and automatically
See also this related question:
https://superuser.com/questions/147873/ssh-sessions-in-xterms-freeze-for-many-minutes-whenever-they-disconnect
Original question:
It would be nice if there were a way to ssh to a machine and immediately reconnect to a specific screen session. You can do this:
laptop> ssh server.com screen -ls
and it will show a list of screens available on server.com like so [1]:
123.pts-1
456.pts-2
And then you might try to do this:
laptop> ssh server.com screen -dr pts-2
but that fails, saying "Must be connected to a terminal."
You have to ssh in first and then do the "screen -dr pts-2" on server.com which is no good if you have a flaky connection and get disconnected a lot. You want to be able to resume with a simple "up-arrow enter" on the laptop. (Or perhaps make it even more automatic.)
I have a rihackulous solution to this problem which I'll post as an answer and hope it gets downvoted to oblivion in favor of the Right Way to deal with this.
Footnotes:
[1] Or, better, if you created the screen sessions with names like "screen -S foo" and "screen -S bar" then you'll get a friendlier list like:
123.foo
456.bar
and can reconnect with, eg, "screen -dr foo".
Mini screen tutorial, incorporating the answer to this question:
Login in to server.com and do
screen -S foo
and then never log out of that session again.
To reconnect to it from elsewhere, do
ssh -t server.com screen -dr foo
To list available screens to reconect to:
screen -ls
or, of course,
ssh server.com screen -ls
to check on server.com's available screens remotely.
I now use the following alias (tcsh), based on Jason's answer below, to connect to a named screen if it exists or create and connect otherwise:
alias ssc 'ssh -t \!:1 "screen -S \!:2 -dr || screen -S \!:2"'
Does the -t option do what you want?
-t Force pseudo-tty allocation. This can be used to execute arbi-
trary screen-based programs on a remote machine, which can be
very useful, e.g. when implementing menu services. Multiple -t
options force tty allocation, even if ssh has no local tty.
So:
laptop> ssh -t server.com screen -dr pts-2
This seems to work in my installation.
This is now subsumed by this: Using GNU Screen completely transparently and automatically
Here's a script, ssc, that works just like ssh but takes a third argument to specify the screen to reconnect to, or the name of a new screen.
I believe this script subsumes everything in the original question.
#!/usr/bin/env perl
# Use 'ssc' (this script) instead of 'ssh' to log into a remote machine.
# Without a 3rd argument it will list available screens.
# Give it a 3rd argument to attach to an existing screen or specify a new
# screen. Eg, ssc remote.com foo
# The numbers in front of the screen tag can usually be ignored.
# Screen is a little too clever though in that if there's an existing screen "bar"
# and you say "ssc remote.com b" it will reconnect you to "bar" instead of making
# a new screen "b". It's like invisible and silent tab-completion.
if(scalar(#ARGV)==0 || scalar(#ARGV) > 2) {
print "USAGE: ssc remote.com [screen name]\n";
} elsif (scalar(#ARGV) == 1) {
$machine = shift;
#screens = split("\n", `ssh $machine screen -ls`);
for(#screens) {
if(/^\s*(\d+)\.(\S+)\s+\(([^\)]*)\)/) {
($num, $tag, $status) = ($1, $2, $3);
if($status =~ /attached/i) { $att{"$num.$tag"} = 1; }
elsif($status =~ /detached/i) { $att{"$num.$tag"} = 0; }
else { print "Couldn't parse this: $_\n"; }
}
}
print "ATTACHED screens:\n";
for(keys(%att)) { print " $_\n" if $att{$_}; }
print "DETACHED screens:\n";
for(keys(%att)) { print " $_\n" unless $att{$_}; }
} else {
$machine = shift;
$tag = shift;
system("ssh -t $machine \"screen -S $tag -dr || screen -S $tag\"");
}
Use the -t option to ssh to allocate a terminal while directly running a command.
laptop> ssh -t server.com screen -dr pts-2
I've been working on something similar but not quite got there, your solutions have solved my problem so here's my suggestion:
ssh -t server.com "screen -S foo -rd || screen -S foo"
This just tries to open the existing screen named foo and if it doesnt exist, creates it.
I'll put this in a launcher on my laptop, so when the wireless network goes I can just open where I left off.
Just noticed that the default screen shell is a bit weak, so an improvement which sets up your home environment a little better is:
ssh -t server.com "screen -S foo -rd || screen -S foo bash -l"
I converted this to work on OS X .bash_profile with one addition: If no 2nd parameter is given, it will start a session "default".
function ssc() {
if [[ -z $2 ]]; then
screen="default"
else
screen=$2
fi
ssh -t $1 "screen -S $screen -dr || screen -S $screen"
}
If you like to connect to the same session always even it is active, detached or not exists yet:
ssh -t user#server screen -xR screenName
The same but create a new session if it is already active on some other pty:
ssh -t user#server screen -rR screenName